#%RAML 1.0
title: Lighthouse REST API
version: v1
documentation:
- title: Lighthouse REST API
  content: This API allows control and inspection of an Opengear Lighthouse management instance.
baseUri: https://{lighthousehost}/api/v1
protocols: [ HTTPS ]

securitySchemes:
  token:
    description: Lighthouse base authentication scheme
    type: Basic Authentication
    describedBy:
      headers:
        Authorization:
          description: authorization session token
          type: string
          required: true
          displayName: Authorization
          example: Token 521a00e57d4a461b3e4bb0c55166f97c

types:
  error:
      type: object
      properties:
        error:
          type: array
          description: A list of errors
          required: true
          items:
            type: object
            properties:
              type:
                type: integer
                required: true
              code:
                type: integer
                required: true
              level:
                type: integer
                required: true
              text:
                type: string
              args:
                type: object

  credentials:
      type: object
      items:
      properties:
        username:
          type: string
          required: true
        password:
          type: string
          required: true

  getSessionResponse:
      type: object
      properties:
        state:
          type: string
        session:
          type: string
        user:
          type: string
          required: false
        last_challenge:
          type: string
          required: false

  setUser:
      type: object
      properties:
        user:
          type: object

  getUserResponse:
      type: object
      properties:
        user:
          type: user

  user:
    type: object
    properties:
      "id": string
      "username": string
      "description": string
      "enabled": boolean
      "rights": entityRights
      "groups":
        type: array
        items: string

  getGroupResponse:
      "type": "object"
      "properties":
        "group":
          "type": "object"
          "properties":
            "id": string
            "groupname":
              "type": "string"
            "mode":
              "type": "string"
            "global_roles":
              "type": "string"
              required: false
            "smart_group_roles":
              "type": "string"
              required: false
            "smart_group":
              "type": "string"
              required: false
            "description":
              "type": "string"
              required: false
            "members":
              "type": "array"
              "items":
                "type": "string"
            rights: entityRights

  setGroup:
      "type": "object"
      "properties":
        "group":
          "type": "object"
          "properties":
            "groupname":
              "type": "string"
              "required": true
            "mode":
              "type": "string"
              "required": true
            "global_roles":
              "type": "string"
              "required": false
            "smart_group_roles":
              "type": "string"
              "required": false
            "smart_group":
              "type": "string"
              "required": false
            "description":
              "type": "string"
              "required": false

  responseToSessionChallenge:
      type: object
      properties:
        session:
          type: string
          required: true
        state:
          type: object
          required: true
        challenge:
          description: Next challenge (if any)
          type: string

  deleteSessionResponse:
      type: object
      properties:
        session:
          type: string
          required: true
        success:
          type: string
          required: true
        state:
          type: string
        user:
          type: string

  extendSessionResponse:
      type: object
      properties:
        session:
          type: string
        success:
          type: boolean
        state:
          type: object
        seconds_remaining:
          type: integer
          format: int32

  getNodesResponse:
      type: object
      properties:
        "nodes":
          type: array
          items:
            description: "Lighthouse client node"
            type: object
            properties:
              "status":
                required: true
                type: string
                enum: [
                  "Enrolled",
                  "Registering",
                  "Registered",
                  "Unknown",
                  "Pending"
                ]
              name:
                required: true
                type: string
              "id":
                required: true
                type: string
              "lhvpn_address":
                type: string
              "runtime_status":
                type: object
                properties :
                  "change_time":
                      type: integer
                  "action_status":
                      type: string
                      enum: [
                        "in progress",
                        "finished",
                        "error",
                        "unknown"
                      ]
                  "id" :
                      type: string
                  "action_type":
                      type: string
                      enum: [
                        "registration",
                        "enrollment",
                        "none"
                      ]
                  "connection_status":
                    type: string
                    enum: [
                      "connected",
                      "pending",
                      "disconnected",
                      "unknown",
                      "never seen"
                    ]
                  "action_error_message":
                    type: string
              "ports":
                type: array
                items:
                  type: object
                  properties:
                    "id": string
                    "label": string
                    "mode":
                      type: string
                      enum: [
                        "disabled",
                        "localConsole",
                        "consoleServer",
                        "sdtServer",
                        "bridge",
                        "terminalServer",
                        "reserved",
                        "powerman",
                        "unknown"
                      ]
                    proxied_ssh_url:
                      type: string
                      description: "URI to ssh to a port on a Lighthouse-enrolled node"
                      example: "ssh://username:consoleserver:portnumber@lhip"
              "tag_list":
                type: object
                properties:
                  "id": string
                  rights: entityRights
                  "tags":
                    type: array
                    items:
                      properties:
                        "id": string
                        name: string
                        "value": string
              rights: entityRights
              model: string
              firmware_version: string
              mac_address: string
              serial_number: string
              enrollment_bundle: string
              interfaces:
                type: array
                items:
                  type: object
                  properties:
                    name: string
                    ipv4_addr: string
                    ipv6_addr: string
        "meta":
          type: object
          properties:
            "searchId":
              type: string
              required: false
            "total_pages": integer

  new_node:
      type: object
      properties:
        "enrollment":
          type: object
          properties:
            "product":
              type: string
              required: false
            "call_home":
              type: "boolean"
              required: false
            "hostname":
              type: string
              required: false
            "bundle":
              type: string
              required: false
            "token":
              type: string
              required: false
            name:
              type: string
              required: false
            "address":
              type: string
              required: false
            "username":
              type: string
              required: false
            "password":
              type: string
              required: false
            "auto_approve":
              type: "boolean"
              required: false
            "connection_method":
              type: string
              required: false
            "base_port":
              type: integer
              required: false
            "port_count":
              type: integer
              required: false
            "port_labels":
              type: array
              required: false
              items:
                type: string

  findNodeByIDResponse:
      description: "Lighthouse client node"
      type: object
      properties:
        node:
          type: object
          properties:
            "status":
              type: string
              enum: [
                "Enrolled",
                "Registering",
                "Registered",
                "Unknown",
                "Pending"
              ]
            name:
              type: string
            "id":
              type: string
            "lhvpn_address":
              type: string
            "runtime_status":
              type: object
              properties :
                "change_time" :
                    type: integer
                "action_status" :
                    type: string
                    enum: [
                      "in progress",
                      "finished",
                      "error",
                      "unknown"
                    ]
                "id" :
                    type: string
                "action_type":
                    type: string
                    enum: [
                      "registration",
                      "enrollment",
                      "none"
                    ]
                "connection_status":
                  type: string
                  enum: [
                    "connected",
                    "pending",
                    "disconnected",
                    "unknown",
                    "never seen"
                  ]
                "action_error_message":
                  type: string
            "tag_list":
              type: object
              properties:
                "id": string
                rights: entityRights
                "tags":
                  type: array
                  items:
                    properties:
                      "id": string
                      name: string
                      "value": string
            rights: entityRights
            model: string
            firmware_version: string
            mac_address: string
            serial_number: string
            enrollment_bundle: string
            interfaces:
              type: array
              items:
                type: object
                properties:
                  name: string
                  ipv4_addr: string
                  ipv6_addr: string

  getNodeIdsResponse:
      type: object
      properties:
        "nodes":
          type: array
          items:
              type: string
        "meta": metaResponse

  put_node:
      type: object
      properties:
        node:
          type: object
          properties:
            name:
              type: string
              required: true
            "mac_address": string
            description:
              type: string
              required: true
            "approved":
              type: integer
              required: true
            "tags":
              type: array
              items:
                type: object
                properties:
                  "id": string
                  name: string
                  "value": string

  getPortByIdResponse:
      type: object
      properties:
        "id":
          required: true
          type: string
        "mode":
          type: string
          enum: [
            "disabled",
            "localConsole",
            "consoleServer",
            "sdtServer",
            "bridge",
            "terminalServer",
            "reserved",
            "powerman",
            "unknown"
          ]
        "port_csid":
          type: string
        "label":
          type: string
        "proxied_ssh_url":
          type: string
          description: "URI to ssh to a port on a Lighthouse-enrolled node"
          example: "ssh://username:consoleserver:portnumber@lhip"
        "web_terminal_url":
          type: string
        "node_name":
          type: string
        "ssh_enabled":
          type: boolean
        "webshell_enabled":
          type: boolean
        "runtime_status":
          type: object
          properties :
            "change_time":
                type: integer
            "change_delta":
                type: integer
            "action_status":
                type: string
                enum: [
                  "in progress",
                  "finished",
                  "error",
                  "unknown"
                ]
            "id" :
                type: string
            "action_type":
                type: string
                enum: [
                  "registration",
                  "enrollment",
                  "none"
                ]
            "connection_status":
              type: string
              enum: [
                "connected",
                "pending",
                "disconnected",
                "unknown",
                "never seen"
              ]
            "action_error_message":
              type: string
              required: false

  getPortByIdResponseList:
      type: object
      properties:
        "ports":
          type: array
          items:
              type: getPortByIdResponse
        meta: metaResponse

  registrationPackageResponse:
      type: object
      properties:
        "cert":
          type: string
        "key":
          type: string
        "ca":
          type: string
        "address":
          type: string
        "ignore_date_header":
          type: "boolean"

  getSearchResponse:
      type: object
      properties:
        "search":
          type: object
          properties:
            "id":
              type: string

  searchFieldsResponse:
      type: object
      properties:
        "fields":
          type: array
          items:
            type: string

  getNodeTagsResponse:
      type: object
      properties:
        "tags":
          type: array
          items:
            properties:
              "id": string
              name: string
              "value": string

  createNodeTag:
      type: object
      properties:
        "tag":
          required: true
          type: object
          properties:
            name:
              type: string
              required: true
            "value":
              type: string
              required: true

  getTagsListResponse:
      type: object
      description: "A list of tags and associated information"
      properties:
        meta: metaResponse
        nodeTags:
          type: array
          items:
            type: object
            properties:
              "id":
                type: string
              name:
                type: string
              values:
                type: array
                description: "A list of values associated with this tag"
                items:
                  type: object
                  properties:
                    "id": string
                    "value": string
              rights: entityRights

  getInterfaceList :
    description: "A list of network interfaces"
    type: object
    properties:
      "meta": metaResponse
      interfaces:
        type: array
        items:
          properties:
            "enabled":
              type: "boolean"
            description:
              type: string
            "media":
              type: string
            "netmask":
              type: string
              required: false
            "physif":
              type: string
            "role":
              type: string
            name:
              type: string
            "address":
              type: string
              required: false
            "gateway":
              type: string
              required: false
            "mode":
              type: string
            "runtime_status":
              type: object
              properties:
                "status":
                  type: string
                "last_status_change":
                  type: number
                "id":
                  type: string
                "dhcp_netmask":
                  type: string
                  required: false
                "dhcp_gateway":
                  type: string
                  required: false
                "dhcp_dns":
                  type: string
                  required: false
                "dhcp_address":
                  type: string
                  required: false
            "dhcp_vendor_class":
              type: string
              required: false
            "id":
              type: string


  interfaceItem:
      type: object
      description: "A list of network interfaces"
      properties:
        interface:
          type: object
          properties:
            "id":
              type: string
              required: false
            "enabled":
              type: "boolean"
            description:
              type: string
            "media":
              type: string
            "netmask":
              type: string
              required: false
            "physif":
              type: string
            "role":
              type: string
            name:
              type: string
            "address":
              type: string
              required: false
            "gateway":
              type: string
              required: false
            "mode":
              type: string
            "runtime_status":
              type: object
              properties:
                "status":
                  type: string
                "last_status_change":
                  type: number
                "id":
                  type: string
              required: false

  getSupportReport:
      type: object
      description: "A concise system report"
      properties:
        "support_report":
          type: object
          properties:
            "contents":
              type: string
              description: "A new line delimited dump of the current state of the system."
              required: true
            "zip_file":
              type: string
              description: "url to a zip file which contains the system report."
              required: true

  systemHostname:
    type: object
    properties:
      system_hostname:
        type: object
        properties:
          hostname: string

  systemTimezone:
    type: object
    properties:
        system_timezone:
          type: object
          properties:
            timezone: string

  systemTime:
    type: object
    properties:
      time:
        type: object
        properties:
          time:
            type: string

  systemGlobalEnrollmentToken:
    type: object
    properties:
      system_global_enrollment_token:
        type: object
        properties:
          token: string

  manifestLink:
    type: object
    properties:
      system_global_manifest_link:
        type: object
        properties:
          url: string

  systemAddress:
    type: object
    properties:
        system_external_address:
          type: object
          properties:
                external_address: string
                os_default_external_address: string

  systemWebui:
    type: object
    properties:
      system_webui_session_timeout:
        type: object
        properties:
          timeout: integer

  connectionSummaryResponse:
    type: object
    properties:
      connectionSummary:
        type: array
        items:
          properties:
            "status":
              required: true
              type: string
              enum: [
                "connected",
                "pending",
                "disconnected"
              ]
            "count":
              type: integer
              required: true

  create_tag:
      type: object
      properties:
        nodeTag:
          type: object
          properties:
            name:
              type: string
              required: true
            values:
              type: array
              required: true


  bundle:
      description: "Lighthouse configuration bundle"
      type: object
      properties:
        bundle:
          type: object
          properties:
            "id": string
            name:
              type: string
            auto_approve:
              type: "boolean"
            token:
              type: string
            automatic_tags:
              type: array
              items:
                description: "Lighthouse client node"
                type: object
                properties:
                  "id":
                    type: string
                  name:
                    type: string
                  "value":
                    type: string
            "nodes":
              type: array
              items:
                type: string
            "manifest_link":
              type: string

  put_tag:
      type: object
      properties:
        nodeTag:
          type: object
          properties:
            name:
              type: string
              required: true
            values:
              type: array
              required: true

  consoleGatewayResponse:
    type: object
    properties:
      console_gateway:
        type: object
        properties:
          ssh_url_delimiter:
            type: string
            required: true

  consoleGatewayPut:
      type: object
      properties:
        console_gateway:
          type: object
          properties:
            ssh_url_delimiter:
              type: string
              required: true

  entityRights:
    type: object
    properties:
      create:
        type: boolean
        required: false
      "delete": boolean
      modify: boolean

  metaResponse:
    type: object
    properties:
      "searchId":
        type: string
        required: false
      "total_pages": integer

  firmwareUpgradeStatus:
    type: object
    properties:
      system_firmware_upgrade_status:
        type: object
        properties:
          state:
            required: true
            type: string
            enum: [
              "pending",
              "running",
              "error",
              "finished"
            ]
          error_message:
            required: false
            type: string
            enum: [
              "format_error",
              "download_error",
              "version_error",
              "runtime_error"
            ]

  entitlements:
    type: object
    properties:
      id:
        type: string
        required: true
      contact:
        type: object
        required: true
        properties:
          name:
            type: string
            required: true
          email:
            type: string
            required: true
          phone:
            type: string
            required: false
      features:
        type: object
        required: true
        properties:
          maintenance:
            type: integer
            required: true
          nodes:
            type: integer
            required: true
          additional:
            type: object
            required: false

  license:
    type: object
    properties:
      id:
        type: integer
        required: false
      raw:
        type: string
        required: true

resourceTypes:
  base-type:
    get?:
      securedBy: [ token ]
      headers:
        Authorization:
          displayName: Authorization
          example: Token {{sessionUid}}
      responses:
        400:
          body:
            application/json:
              type: error
        401:
          description: Authentication failure
          body:
            application/json:
              type: error
              examples:
                example1:
                  value: {
                    "error": [
                      {
                        type: 7,
                        "code": 42,
                        "text": "Invalid session ID",
                        "args": {},
                        "level": 1
                      }
                    ]
                  }
                example2:
                  value: {
                    "error": [
                      {
                        type: 7,
                        "code": 46,
                        "text": "Permission denied",
                        "args": {},
                        "level": 1
                      }
                    ]
                  }

    post?:
      securedBy: [ token ]
      headers:
        Authorization:
          displayName: Authorization
          example: Token {{sessionUid}}
      responses:
        400:
          body:
            application/json:
              type: error
        401:
          description: Authentication failure
          body:
            application/json:
              type: error
              example:
                {
                  "error": [
                    {
                      type: 7,
                      "code": 42,
                      "text": "Invalid session ID",
                      "args": {},
                      "level": 1
                    }
                  ]
                }
    put?:
      securedBy: [ token ]
      headers:
        Authorization:
          displayName: Authorization
          example: Token {{sessionUid}}
      responses:
        400:
          body:
            application/json:
              type: error
        401:
          description: Authentication failure
          body:
            application/json:
              type: error
              example:
                {
                  "error": [
                    {
                      type: 7,
                      "code": 42,
                      "text": "Invalid session ID",
                      "args": {},
                      "level": 1
                    }
                  ]
                }
        404:
          description: Not found
          body:
            application/json:
              type: error
        500:
          description: Internal error
          body:
            application/json:
              type: error
    delete?:
      securedBy: [ token ]
      headers:
        Authorization:
          displayName: Authorization
          example: Token {{sessionUid}}
      responses:
        400:
          description: Incomplete data
          body:
            application/json:
              type: error
        401:
          description: Authentication failure
          body:
            application/json:
              type: error
              example:
                {
                  "error": [
                    {
                      type: 7,
                      "code": 42,
                      "text": "Invalid session ID",
                      "args": {},
                      "level": 1
                    }
                  ]
                }
    patch?:
      securedBy: [ token ]
      headers:
        Authorization:
          displayName: Authorization
          example: Token {{sessionUid}}
      responses:
        400:
          body:
            application/json:
              type: error
        401:
          description: Authentication failure
          body:
            application/json:
              type: error
              example:
                {
                  "error": [
                    {
                      type: 7,
                      "code": 42,
                      "text": "Invalid session ID",
                      "args": {},
                      "level": 1
                    }
                  ]
                }
  searchable-type:
    type: base-type
    get:
      queryParameters:
        per_page:
          description: Number of items expected per page
          type: integer
          required: false
          displayName: per_page
          default: 100000
        page:
          description: The page to return (indexed from 1)
          type: integer
          required: false
          displayName: page
          default: 1
        json:
          description: >
            One or more json URL encoded search parameters.


            Example
            %7B%22type%22%3A1%2C%22items%22%3A%5B%7B%22datatype%22%3A4
            %2C%22type%22%3A3%2C%22oper%22%3A1%2C%22fieldname%22%3A%22
            config%3Aname%22%2C%22value%22%3A%22test%22%7D%5D%7D


            which is the URL encoded json


            {type:1,items:[{"datatype":4,type:3,"oper":1,"fieldname":"config:name","value":"test"}]}
          type: string
          required: false
          displayName: 'json'
        jb64:
          description: >
            one or more base64 encoded json search parameters.


            Ensure that any trailing = padding is URL encoded to %3D
          type: string
          required: false
          displayName: 'jb64'
        searchparameters:
          description: >
            One or more search fields as provided by /nodes/fields.


            For example,

            config:name=\*test\*, will search for nodes with names containing
            test, or


            config:status=!Enrolled will search for
            nodes which are not enrolled.


            Allowed operators are: =value, >value, >=value, <value, <=value,
            !value (not), \*value (ends in), value\* (starts with), \*value\*
            (contains). Reserved characters to be URl encoded, e.g. = as %3D
          type: string
          required: false
          displayName: 'search parameters*'
        operator:
          description: >
            Operator applied between all searchparameters, json and jb64
            query parameters.


            AND or OR

          default: AND
          required: false
        searchId:
          description: >
            Lighthouse maintains search results for a limited timespan,
            which allows the user to paginate through results.
            The searchId is returned in meta data of a normal search and can
            then be used as a parameter to retrieve the same results. When
            searchId is used, no other search parameter may be included,
            only page and per_page can be used to proceed through pagination.
          type: string
          required: false
          displayName: 'searchId'
      responses:
        400:
          description: >
            Invalid request:
            Missing or incorrect page/per_page.
            Invalid Condition value.
            Invalid search parameter.
            Invalid json/jb64 parameter.
          body:
            application/json:
              type: error
              example:
                {
                  "error": [
                    {
                      type: 4,
                      "code": 48,
                      "text": "Invalid parameter 'config:nam' was provided",
                      "args": {
                        "param": "config:nam"
                      },
                      "level": 1
                    },
                    {
                      type: 2,
                      "code": 49,
                      "text": "Invalid json '{\"type\":1,\"items\":{\"datatype\":4,\"type\":3,\"oper\":1,\"fieldname\":\"config:name\",\"value\":\"test\"}]}' for parameter 'json'",
                      "args": {
                        "line": "1",
                        "position": "92",
                        "value": "{\"type\":1,\"items\":{\"datatype\":4,\"type\":3,\"oper\":1,\"fieldname\":\"config:name\",\"value\":\"test\"}]}",
                        "column": "92",
                        "error": "'}' expected near ']'",
                        "param": "json"
                      },
                      "level": 1
                    },
                    {
                      type: 4,
                      "code": 39,
                      "text": "Invalid request body",
                      "args": {},
                      "level": 1
                    }
                  ]
                }

/sessions:
  description: >
    The sessions endpoint is used to authenticate the user and create a
    session token for accessing all other Lighthouse endpoints.
  # Auth.session_create
  post:
    displayName: createSession
    description: Create a new authenticated session.
    body:
      application/json:
        type: credentials
        example:
          {"username":"root","password":"default"}
    responses:
      400:
        description: Failed to initiate session creation due to error in post body.
        body:
          application/json:
            example:
              {
                "error": [
                  {
                    type: 4,
                    "code": 40,
                    "text": "Required field 'username' was not provided in the request",
                    "args": {
                      "param": "username"
                    },
                    "level": 1
                  },
                  {
                    type: 4,
                    "code": 40,
                    "text": "Required field 'password' was not provided in the request",
                    "args": {
                      "param": "password"
                    },
                    "level": 1
                  }
                ]
              }
      401:
        description: Authentication failed due to invalid credentials or session.
        body:
          application/json:
            example:
              {
                "error": [
                  {
                    type: 7,
                    "code": 41,
                    "text": "Invalid login credentials",
                    "args": {},
                    "level": 1
                  }
                ]
              }
      303:
        description: Redirect to new authentication session
        body:
          application/json:
            example:
              {
                "sid": "71dcba707b6c177644ede1b224f69096",
                "message": "Redirecting to new session at {redirect-url}"
              }
      200:
          body:
            application/json:
              type: getSessionResponse
              example:
                {
                  "state": "authenticated",
                  "session": "71dcba707b6c177644ede1b224f69096",
                  "user": "root"
                }
  /{sessionUid}:
    type: base-type
    # Auth.session_get
    get:
      displayName: getSession
      description: >
        Retrieve the state of an authentication session by ID. A session ID may
        be valid for some period after the user logs out.
      responses:
        200:
          description: Session exists
          body:
            application/json:
              type: getSessionResponse
              example:
                {
                  "state": "authenticated",
                  "session": "71dcba707b6c177644ede1b224f69096",
                  "user": "root"
                }
        400:
          description: Session does not exist
          body:
            application/json:
              type: getSessionResponse
              example:
                {
                  "state": "unknown",
                  "session": "4cf7ff89791062c2eddcbb7778d532a"
                }
        404:
          description: Session does not exist
          body:
            application/json:
              example:
                {
                  "state": "unknown",
                  "session": "4cf7ff89791062c2eddcbb7778d532a"
                }
    # Auth.session_apply_response
    put:
      body:
        application/json:
          type: responseToSessionChallenge
      displayName: responseToSessionChallenge
      description: Apply a challenge response to a session
      responses:
        200:
          description: Response applied. Next challenge in {challenge} if required.
          body:
            application/json:
              type: responseToSessionChallenge
        400:
          description: Invalid request
          body:
            application/json:
              example:
                {
                  "error": [
                    {
                      type: 4,
                      "code": 39,
                      "text": "Invalid request body",
                      "args": {},
                      "level": 1
                    }
                  ]
                }
        403:
          description: Authentication failed. No more attempts allowed.
        404:
          description: Authentication failed.
    # Auth.session_delete
    delete:
      displayName: deleteSession
      description: Log out of and delete a session
      responses:
        200:
          description: Session deleted
          body:
            application/json:
              type: deleteSessionResponse
        404:
          description: Session did not exist

/nodes:
  type: searchable-type
  description: >
    Creating/registering and viewing the state of console server nodes.
  # Node.get_node_list
  get:
    displayName: getNodes
    description: >
      Gets nodes attached to this lighthouse instance.


      Any number of search query parameters can be provided to perform an
      ANDed search on the nodes. The parameters possible should be retrieved
      with GET /nodes/fields. The list provided is dynamic.


      The standard ember-data pagination fields {per_page} and {page} apply
      to this list.


      {per_page} and {page} are optional but both are to be supplied if pages
      are requested.

      A node response will also contain a list of tags, which represents the
      user-editable attributes assigned to this node.
    queryParameters:
      per_page:
        description: Number of nodes expected per page
        type: integer
        required: false
        displayName: per_page
        default: 100000
      page:
        description: The page to return (indexed from 1)
        type: integer
        required: false
        displayName: page
        default: 1
      searchparameters:
        description: One or more search fields as provided by /nodes/fields
        type: string
        required: false
        displayName: 'search parameters*'
    responses:
      200:
        description: The array of nodes, either a full or as requested by parameters
        body:
          application/json:
            type: getNodesResponse
            example:
              {
                "nodes": [
                  {
                    "name": "test",
                    "id": "nodes-1",
                    "lhvpn_address": "192.168.128.2",
                    "runtime_status": {
                      "change_time": 0,
                      "action_status": "unknown",
                      "id": "nodes-1",
                      "action_type": "none",
                      "connection_status": "unknown",
                      "action_error_message": ""
                    },
                    "tag_list": {
                        "id": "nodes-1",
                        "tags": [
                          {
                            "id": "nodes_tags-4",
                            "name": "Location",
                            "value": "Hong Kong"
                          }
                        ],
                        "rights": {
                            "create": true,
                            "modify": true,
                            "delete": true
                        }
                    },
                    "ports": [
                      {
                        "id": "port1",
                        "label": "User Label",
                        "mode": "disabled",
                        "proxied_ssh_url": ""
                      }
                    ],
                    "status": "Enrolled",
                    "rights": {
                      "delete": true,
                      "modify": true
                    },
                    "enrollment_bundle": "Global",
                    "mac_address": "00:13:c6:02:47:99",
                    "serial_number": "70000002451668",
                    "model": "ACM7004-5-LMR",
                    "interfaces": [],
                    "firmware_version": "4.0.0"
                  },
                  {
                    "name": "test3",
                    "id": "nodes-2",
                    "lhvpn_address": "192.168.128.3",
                    "runtime_status": {
                      "change_time": 1471516371,
                      "action_status": "error",
                      "id": "nodes-2",
                      "action_error_message": "Failed to contact node.",
                      "action_type": "registration",
                      "connection_status": "never seen"
                    },
                    "ports": [
                      {
                        "id": "port1",
                        "label": "User Label",
                        "mode": "disabled",
                        "proxied_ssh_url": ""
                      }
                    ],
                    "tag_list": {
                        "id": "nodes-1",
                        "tags": [],
                        "rights": {
                            "create": true,
                            "modify": true,
                            "delete": true
                        }
                    },
                    "status": "Registering",
                    "rights": {
                      "delete": true,
                      "modify": true
                    },
                    "enrollment_bundle": "Global",
                    "mac_address": "00:13:c6:02:5a:d5",
                    "serial_number": "71480488331675",
                    "model": "CM7148-2-DAC",
                    "interfaces": [],
                    "firmware_version": "4.0.0"
                  }
                ],
                "meta": {
                  "total_pages": 1
                }
              }
      400:
        description: Invalid request, missing or incorrect page/per_page
        body:
          application/json:
            type: error
            example:
              {
                "error": [
                  {
                    type: 4,
                    "code": 39,
                    "text": "Invalid request body",
                    "args": {},
                    "level": 1
                  }
                ]
              }
      404:
        description: Invalid request, Incomplete data, Node not found, Failure during retrieval of nodes
        body:
          application/json:
            type: error
      500:
        description: Failed to read nodes.
        body:
          application/json:
            type: error
  # Enrollment.registration
  post:
    body:
      application/json:
        type: new_node
        examples:
          example1:
            {
              "enrollment":
              {
                "product": "opengear",
                "call_home": true,
                "token":"ABCDEFGHIJKLMNOPQRSTUVWXYZ123456",
                "bundle":"console-servers",
                "hostname":"acm7004-5"
              }
            }
          example2:
            {
              "enrollment":
              {
                "product": "opengear",
                "call_home": false,
                "name":"bne-7004-backup",
                "address":"1.2.3.4",
                "username":"root",
                "password":"default",
                "auto_approve":true
              }
            }
          example3:
            {
              "enrollment":
              {
                "product": "generic",
                "name":"bne-7004-backup",
                "address":"1.2.3.4",
                "connection_method": "ssh",
                "username":"root",
                "password":"default",
                "auto_approve":true,
                "base_port": 2100,
                "port_count": 2,
                "port_labels": [
                  "Port 1",
                  "Port 2"
                ]
              }
            }

    displayName: enrollNewNode
    description: >
      Enqueue a new node for enrollment. This can either be a direct (Lighthouse-driven) enrollment, or a enrollment request by a new node ("call-home").

      The "call-home" parameter in the enrollment request body dictates what style it should be. If true, the request is not authenticated with a sesstion token (ie. from the web UI), but an enrollment request token. The caller should also pass a hostname to be used for the node name, and can optionally pass a bundle identifier to request enrollment against a specific bundle.

      If the enrollment is not "call-home", but directly driven from the Lighthouse, the request should be in an authenticted session, and provide the node details (name, address, username, password and auto-approve). The address must be a valid IPv4 address.
    responses:
      202:
        description: Enrollment initiated, but not yet complete. Client can poll for registration package using given UUID and enrollment package password.
        body:
          application/json:
            example:
              {
                 "message": "Enrollment initiated: new registration package will be available soon",
                 "uuid": "{uuid}",
                 "package_password": "{package_password}"
              }
      303:
        description: Redirect to new node session
        body:
          application/json:
            example:
              {
                "message": "Redirecting to new node at {redirect-url}"}
      400:
        description: Invalid request, or error with supplied data (eg. incorrect IP address)
        body:
          application/json:
            example:
              {
                "error": [
                  {
                    type: 4,
                    "code": 39,
                    "text": "Invalid request body",
                    "args": {},
                    "level": 1
                  }
                ]
              }
      500:
        description: Unexpected error, including failure to start enrollment due to internal error.
        body:
          application/json:
            example:
              {
                "error": [
                  {
                    type: 2,
                    "code": 26,
                    "text": "Duplicate 'name' fields with value 'test'",
                    "args": {
                      "value": "test",
                      "uuid": "root-1-@nodes",
                      "field": "name"
                    },
                    "level": 1
                  },
                  {
                    type: 1,
                    "code": 33,
                    "text": "Push command failed",
                    "args": {},
                    "level": 1
                  }
                ]
              }
  /smartgroups:
    type: base-type
    get:
      displayName: getNodeSmartgroupList
      description: Retrieve a list of node smart groups
      responses:
        200:
          description: A list of nodes
          body:
            application/json:
              example:
                {
                  "meta": {
                    "total_pages": 1
                  },
                  "smartgroups": [
                    {
                      "id": "smart_groups_node_groups-1",
                      name: "X",
                      "rights": {
                        "delete": true,
                        "modify": true
                      },
                      "query": "{\"type\": 2, \"fieldname\": \"config:blah\", \"oper\": 3, \"datatype\": 2}"
                    },
                    {
                      "id": "smart_groups_node_groups-5",
                      name: "X3",
                      "rights": {
                        "delete": true,
                        "modify": true
                      },
                      "query": "{\"type\": 2, \"fieldname\": \"config:blah\", \"oper\": 3, \"datatype\": 2}"
                    },
                    {
                      "id": "smart_groups_node_groups-6",
                      name: "X4",
                      "rights": {
                        "delete": true,
                        "modify": true
                      },
                      "query": "{\"type\": 2, \"fieldname\": \"config:blah\", \"oper\": 3, \"datatype\": 2}"
                    },
                    {
                      "id": "smart_groups_node_groups-7",
                      name: "X9",
                      "rights": {
                        "delete": true,
                        "modify": true
                      },
                      "query": "{\"type\": 2, \"fieldname\": \"config:blah\", \"oper\": 3, \"datatype\": 2}"
                    },
                    {
                      "id": "smart_groups_node_groups-8",
                      name: "X11",
                      "rights": {
                        "delete": true,
                        "modify": true
                      },
                      "query": "{\"type\": 2, \"fieldname\": \"config:blah\", \"oper\": 3, \"datatype\": 2}"
                    }
                  ]
                }
        500:
          description: Unexpected error
    post:
      displayName: createNodeSmartgroup
      description: Create a new node smart group
      body:
        application/json:
          example:
            {
              "smartgroup": {
                name: "X9",
                "rights": {
                  "delete": true,
                  "modify": true
                },
                "query": "{\"type\": 2, \"fieldname\": \"config:blah\", \"oper\": 3, \"datatype\": 2}"
              }
            }
      responses:
        200:
          description: Smartgroup created successfully.
          body:
            application/json:
              example: |
                {
                  "smartgroup": {
                    "id": "smart_groups_nodes_groups-4",
                    "rights": {
                      "delete": true,
                      "modify": true
                    },
                    "name": "X9",
                    "query": "{\"type\": 2, \"fieldname\": \"config:blah\", \"oper\": 3, \"datatype\": 2}"
                  }
                }
        303:
          description: Redirect to newly created smartgroup.
        400:
          description: >
            Invalid request: body is not json or does not conform to required json schema.
    /{groupId}:
      type: base-type
      get:
        displayName: getNodeSmartgroup
        description: Retrieve the details for a smart group.
        responses:
          200:
            description: Group exists
            body:
              application/json:
                example:
                  {
                    "smartgroup": {
                      "id": "smart_groups_node_groups-1",
                      name: "X",
                      "query": "{\"type\": 2, \"fieldname\": \"config:blah\", \"oper\": 3, \"datatype\": 2}"
                    }
                  }
          404:
            description: Smartgroup does not exist
      delete:
        displayName: deleteNodeSmartgroup
        description: Delete a smart group.
        responses:
          200:
            description: The group was deleted succesfully.
          404:
            description: Smartgroup does not exist
      put:
        displayName: updateNodeSmartgroup
        description: Updates the details for a smart group.
        body:
          application/json:
            example:
              {
                "smartgroup": {
                  name: "X9",
                  "query": "{\"type\": 2, \"fieldname\": \"config:blah\", \"oper\": 3, \"datatype\": 2}"
                }
              }
        responses:
          200:
            description: Succesfully updated
            body:
              application/json:
                example:
                  {
                    "smartgroup": {
                      "id": "smart_groups_node_groups-1",
                      name: "X",
                      "query": "{\"type\": 2, \"fieldname\": \"config:blah\", \"oper\": 3, \"datatype\": 2}"
                    }
                  }
          404:
            description: Smartgroup does not exist
          400:
            description: Request data was not valid or incomplete

  # Node.manifest
  /manifest:
    type: base-type
    get:
      displayName: downloadManifest
      description: Download the system manifest file
      responses:
        200:
          description: The manifest file
          body:
            text/plain:
              example:
                address=192.168.0.1
                password=enrollmentToken
        404:
          description: No manifest file is available
  # Node.get_node
  /{id}:
    type: base-type
    uriParameters:
      id:
        description: ID of the node.
        required: true
        displayName: id
        example: nodes-1
    get:
      displayName: findNodeByID
      description: Find a node by unique ID
      responses:
        200:
          description: The requested node
          body:
            application/json:
              type: findNodeByIDResponse
              example:
                {
                  "node": {
                    "name": "test1",
                    "id": "nodes-1",
                    "lhvpn_address": "192.168.128.2",
                    "runtime_status": {
                      "change_time": 1471950616,
                      "action_status": "in progress",
                      "id": "nodes-1",
                      "action_error_message": "",
                      "action_type": "registration",
                      "connection_status": "never seen"
                    },
                    "tag_list": {
                        "id": "nodes-1",
                        "tags": [
                          {
                            "id": "nodes_tags-4",
                            "name": "Location",
                            "value": "Hong Kong"
                          }
                        ],
                        "rights": {
                            "create": true,
                            "modify": true,
                            "delete": true
                        }
                    },
                    "rights": {
                      "delete": false,
                      "modify": true
                    },
                    "status": "Registering",
                    "enrollment_bundle": "Global",
                    "mac_address": "00:13:c6:02:47:99",
                    "serial_number": "70000002451668",
                    "model": "ACM7004-5-LMR",
                    "interfaces": [],
                    "firmware_version": "4.0.0"
                  }
                }
        404:
          description: Node does not exist
        500:
          description: Unexpected error
      headers:
        Authorization:
          description: authorization session token
          type: string
          required: true
          displayName: Authorization
    put:
      displayName: putNode
      description: Update a node
      body:
        application/json:
          type: put_node
          example:
            {
              "node": {
                name: "test1",
                "mac_address": "AA:BB:CC:DD:EE:FF",
                description: "Test Node",
                "approved": 0,
                "tags": [
                  {
                    "id": "nodes_tags-4",
                    name: "Location",
                    "value": "Hong Kong"
                  }
                ]
              }
            }
      responses:
        200:
          description: The updated node
          body:
            application/json:
              type: findNodeByIDResponse
              example:
                {
                  "node": {
                    name: "test1",
                    "id": "nodes-1",
                    "lhvpn_address": "192.168.128.2",
                    "runtime_status": {
                      "change_time": 1471950616,
                      "action_status": "in progress",
                      "id": "nodes-1",
                      "action_error_message": "",
                      "action_type": "registration",
                      "connection_status": "never seen"
                    },
                    "tag_list": {
                        "id": "nodes-1",
                        "tags": [],
                        "rights": {
                            "create": true,
                            "modify": true,
                            "delete": true
                        }
                    },
                    "rights": {
                      "delete": false,
                      "modify": true
                    },
                    "status": "Registering",
                    "enrollment_bundle": "Global",
                    "mac_address": "00:13:c6:02:47:99",
                    "serial_number": "70000002451668",
                    "model": "ACM7004-5-LMR",
                    "interfaces": [],
                    "firmware_version": "4.0.0"
                  }
                }
    delete:
      description: Delete (unenroll) a node.
      responses:
        204:
          description: The node was deleted successfully.

    # Enrollment.get_registration_package
    /registration_package:
      type: base-type
      get:
        displayName: getNodeRegistrationPackageByID
        description: >
          Retrieve the enrollment package for a node.
        responses:
          200:
            description: The requested enrollment package
            body:
              application/json:
                type: registrationPackageResponse
          500:
            description: Registration package not available for this node
            body:
              application/json:
                example:
                  {
                    "error": [
                      {
                        type: 5,
                        "code": 45,
                        "text": "Registration package is not currently available for this node",
                        "args": {},
                        "level": 1
                      }
                    ]
                  }
          404:
            description: Node does not exist
    # Node.get_tags
    /tags:
      type: base-type
      description: >
        Each node can have a list of tags associated with it. These tags are
        references to a global list of tags, allowing for the grouping of nodes.
        For example one can group nodes into geographical location by assigning
        multiple nodes with a tag (tag="Location", value="New York").
      # Node.get_tags
      get:
        displayName: getNodeTags
        description: >
          Get the list of all tags associated with this node.
        responses:
          200:
            description: The requested enrollment package
            body:
              application/json:
                type: getNodeTagsResponse
                example:
                  {
                    "tags": [
                      {
                        "id": "nodes_tags-1",
                        name: "myTag",
                        "value": "my tag value"
                      },
                      {
                        "id": "nodes_tags-2",
                        name: "myTag2",
                        "value": ""
                      },
                      {
                        "id": "nodes_tags-3",
                        name: "myTag3",
                        "value": "another value"
                      }
                    ]
                  }
          400:
            description: Incomplete data.
          404:
            description: Node does not exist.
      # Node.create_tag
      post:
        displayName: createNodeTag
        description: >
          Create and associate a new tag with the node. If the tag exists
          update or set the value. If no value is given, or the value is emplty,
          the value will be set to null.
        body:
          application/json:
            type: createNodeTag
            example:
              {
                "tag": {
                  name: "Location",
                  "value":"New York"
                }
              }
        responses:
          200:
            body:
              application/json:
                type: getNodeTagsResponse
                description: Node with given node id not found.
                example:
                  {
                    "tags": [
                      {
                        "id": "nodes_tags-1",
                        name: "Location",
                        "value": "New York"
                      }
                    ]
                  }
          400:
            description: >
              Invalid request: body is not json or does not conform to required json schema.

              Incomplete data: name item missing.
          404:
            body:
              application/json:
                type: error
                description: Node with given node id not found.
      /{tag_value_id}:
        type: base-type
        uriParameters:
          tag_value_id:
            description: Identifier for unique tag within given node
            required: true
            displayName: tag_value_id
            example: nodes_tags-1
        # Node.get_tag_from_node
        get:
          description: Get a tag's information by ID.
          responses:
            200:
              description: >
                Tag information in node with {id} and tag identification
                {tag_value_id} successfully retrieved.
              body:
                application/json:
                  examples:
                    example1:
                      {
                        "tag": {
                          "id": "nodes_tags-1",
                          name: "Location",
                          "value": "New York"
                        }
                      }
            400:
              description: >
                Invalid request: body is not json or does not conform to required json schema.

                Incomplete data: node id, or tag_value_id parameter missing.
            404:
              body:
                application/json:
                  type: error
                  description: >
                    Node with given node {id} not found.
                    Tag information with given {tag_value_id} not found.
        # Node.delete_tag
        delete:
          description: Delete a tag value from the node.
          responses:
            200:
              description: The {tag_value_id} tag information was deleted.
            400:
              description: >
                Invalid request: body is not json or does not conform to required json schema.

                Incomplete data: node id, or tag_value_id parameter missing.
            404:
              body:
                application/json:
                  type: error
                  description: >
                    Node with given node {id} not found.

                    Tag information with given {tag_value_id} not found.
                  example:
                    {
                      "error": [
                        {
                          type: 5,
                          "code": 29,
                          "text": "Could not find element with UUID 'nodes_tags-0'",
                          "args": {
                            "uuid": "nodes_tags-0"
                          },
                          "level": 1
                        }
                      ]
                    }
        # Node.update_tag
        put:
          description: Update tag information for {node_tag_id} in node {id}
          body:
            application/json:
              type: createNodeTag
              example:
                {
                  "tag": {
                    name: "Location",
                    "value": "USA.NewYork"
                  }
                }
          responses:
            200:
              description: The {tag_value_id} tag information was updated.
            400:
              description: >
                Invalid request: body is not json or does not conform to required json schema.

                Incomplete data: node id, or tag_value_id parameter missing.
            404:
              body:
                application/json:
                  type: error
                  description: >
                    Node with given node {id} not found.

                    Tag information with given {tag_value_id} not found.
                  example:
                    {
                      "error": [
                        {
                          type: 5,
                          "code": 29,
                          "text": "Could not find element with UUID 'nodes_tags-0'",
                          "args": {
                            "uuid": "nodes_tags-0"
                          },
                          "level": 1
                        }
                      ]
                    }
  /ids:
    type: searchable-type
    get:
      queryParameters:
        per_page:
          description: Number of nodes expected per page
          type: integer
          required: false
          displayName: per_page
          default: 100000
        page:
          description: The page to return (indexed from 1)
          type: integer
          required: false
          displayName: page
          default: 1
        searchparameters:
          description: One or more search fields as provided by /nodes/fields
          type: string
          required: false
          displayName: 'search parameters*'
      displayName: Get node search fields
      description: >
        Obtain a list of node ids, for example /nodes/ids?config:name=test.


        Any number of search query parameters can be provided to perform an
        ANDed search on the nodes. The parameters possible should be retrieved
        with GET /nodes/fields. The list provided is dynamic.


        The standard ember-data pagination fields {per_page} and {page} apply
        to this list.


        {per_page} and {page} are optional but both are to be supplied if pages
        are requested.

      responses:
        200:
          description: The list of search fields
          body:
            application/json:
              type: getNodeIdsResponse
              example:
                {
                  "nodes": [
                    "nodes-1",
                    "nodes-2",
                    "nodes-3",
                    "nodes-4",
                    "nodes-5"
                  ],
                  "meta": {
                    "searchId": "{150f460-743e-11e6-baab-080027032960",
                    "total_pages": 1
                  }
                }
        500:
          description: Unexpected error
      headers:
        Authorization:
          description: authorization session token
          type: string
          required: true
          displayName: Authorization

  # Node.get_search_fields
  /fields:
    type: base-type
    get:
      displayName: Get node search fields
      description: >
        Obtain a list of fields which can be used to perform queries against
        nodes.
      responses:
        200:
          description: The list of search fields
          body:
            application/json:
              type: searchFieldsResponse
              example:
                {
                  "fields": [
                    "config:common_name",
                    "config:description",
                    "config:lhvpn_address",
                    "config:mac_address",
                    "config:name",
                    "config:status",
                    "config:ssh_port",
                    "port:attachedDeviceType",
                    "port:hardwareSettings_pinout",
                    "port:hardwareSettings_protocol",
                    "port:hardwareSettings_uart_baud",
                    "port:hardwareSettings_uart_dataBits",
                    "port:hardwareSettings_uart_flowControl",
                    "port:hardwareSettings_uart_parity",
                    "port:hardwareSettings_uart_stopBits",
                    "port:hardwareType",
                    "port:id",
                    "port:label",
                    "port:logging_facility",
                    "port:logging_level",
                    "port:logging_priority",
                    "port:mode",
                    "port:modeSettings_bridge_rfc2217",
                    "port:modeSettings_bridge_server_address",
                    "port:modeSettings_bridge_server_port",
                    "port:modeSettings_bridge_sshTunnel",
                    "port:modeSettings_consoleServer_general_accumulateMS",
                    "port:modeSettings_consoleServer_general_escapeChar",
                    "port:modeSettings_consoleServer_general_powerMenuEnabled",
                    "port:modeSettings_consoleServer_general_replaceBackspace",
                    "port:modeSettings_consoleServer_portShare_authentication",
                    "port:modeSettings_consoleServer_portShare_enabled",
                    "port:modeSettings_consoleServer_portShare_encryption",
                    "port:modeSettings_consoleServer_portShare_password",
                    "port:modeSettings_consoleServer_rfc2217_enabled",
                    "port:modeSettings_consoleServer_ssh_enabled",
                    "port:modeSettings_consoleServer_tcp_enabled",
                    "port:modeSettings_consoleServer_telnet_enabled",
                    "port:modeSettings_consoleServer_telnet_unauthenticated",
                    "port:modeSettings_consoleServer_webShell_enabled",
                    "port:modeSettings_sdtServer_password",
                    "port:modeSettings_sdtServer_username",
                    "port:modeSettings_terminalServer_terminalType",
                    "port:nagios_enabled",
                    "port:nagios_name",
                    "port:nagios_portLogging",
                    "port:nagios_serialStatus"
                  ]
                }
        500:
          description: Unexpected error
      headers:
        Authorization:
          description: authorization session token
          type: string
          required: true
          displayName: Authorization

  /{id}/ports:
    type: base-type
    get:
      description: >
        Retrieve a list of all ports belonging to a node.
      responses:
        200:
          description: The list of ports belonging to the node
          body:
            application/json:
              type: getPortByIdResponseList

/ports:
  type: searchable-type
  description: >
    Used for working with port information.
  get:
    displayName: getPorts
    description: >
      Gets ports attached to this lighthouse instance.


      Any number of search query parameters can be provided to perform an
      ANDed search on the ports.


      The standard ember-data pagination fields {per_page} and {page} apply
      to this list.


      {per_page} and {page} are optional but both are to be supplied if pages
      are requested.

    queryParameters:
      per_page:
        description: Number of ports expected per page
        type: integer
        required: false
        displayName: per_page
        default: 100000
      page:
        description: The page to return (indexed from 1)
        type: integer
        required: false
        displayName: page
        default: 1
      searchparameters:
        description: One or more search fields
        type: string
        required: false
        displayName: 'search parameters*'
    responses:
      200:
        description: The array of ports, either a full array or as requested by parameters
        body:
          application/json:
            type: getPortByIdResponseList
            example:
              {
                "ports": [{
                  "proxied_ssh_url": "ssh://user:node1:port1@192.168.0.1",
                  "label": "Port 01",
                  "id": "nodes_ports-1",
                  "node_name": "node1",
                  "webshell_enabled": false,
                  "web_terminal_url": "manage/nodes/ports/terminal/node1/port1?name=Port_01",
                  "port_csid": "port1",
                  "mode": "consoleServer",
                  "runtime_status": {
                    "change_delta": 14,
                    "change_time": 1498603761,
                    "action_status": "in progress",
                    "id": "nodes-12",
                    "action_type": "none",
                    "connection_status": "connected"
                  },
                  "ssh_enabled": true
                }],
                "meta": {
                  "searchId": "{4648d82-5b8a-11e7-a476-773c6172a34}",
                  "total_pages": 5
                }
              }
      400:
        description: Invalid request, missing or incorrect page/per_page
        body:
          application/json:
            type: error
            example:
              {
                "error": [
                  {
                    type: 4,
                    "code": 39,
                    "text": "Invalid request body",
                    "args": {},
                    "level": 1
                  }
                ]
              }
      404:
        description: Invalid request, Incomplete data, Port not found, Failure during retrieval of ports
        body:
          application/json:
            type: error
      500:
        description: Failed to read ports.
        body:
          application/json:
            type: error
  /{id}:
    type: base-type
    get:
      description: Retrieve a single port by ID.
      responses:
        200:
          description: Returns properties for a single port.
          body:
            application/json:
              type: getPortByIdResponse

/search:
  type: base-type
  description: >
    Used to perform searches on nodes and ports on the system.
  /nodes:
    type: base-type
    description: >
      Creating a search ID for nodes from the given query parameters.
    get:
      displayName: getSearchId
      description: >
        Gets a search ID for searching nodes attached to this lighthouse instance.

        Any number of search query parameters can be provided to perform an
        ANDed search on the nodes. The parameters possible should be retrieved
        with GET /nodes/fields. The list provided is dynamic.
      queryParameters:
        json:
          description: >
            One or more json URL encoded search parameters.

            Example
            %7B%22type%22%3A1%2C%22items%22%3A%5B%7B%22datatype%22%3A4
            %2C%22type%22%3A3%2C%22oper%22%3A1%2C%22fieldname%22%3A%22
            config%3Aname%22%2C%22value%22%3A%22test%22%7D%5D%7D

            which is the URL encoded json

            {type:1,items:[{"datatype":4,type:3,"oper":1,"fieldname":"config:name","value":"test"}]}
          type: string
          required: false
          displayName: 'json'
        jb64:
          description: >
            one or more base64 encoded json search parameters.

            Ensure that any trailing = padding is URL encoded to %3D
          type: string
          required: false
          displayName: 'jb64'
        searchparameters:
          description: >
            One or more search fields as provided by /nodes/fields.

            For example,

            config:name=\*test\*, will search for nodes with names containing
            test, or

            config:status=!Enrolled will search for
            nodes which are not enrolled.

            Allowed operators are: =value, >value, >=value, <value, <=value,
            !value (not), \*value (ends in), value\* (starts with), \*value\*
            (contains). Reserved characters to be URl encoded, e.g. = as %3D
          type: string
          required: false
          displayName: 'search parameters*'
        operator:
          description: >
            Operator applied between all searchparameters, json and jb64
            query parameters.

            AND or OR

          default: AND
          required: false
      responses:
        200:
          description: The search ID, as defined by given parameters
          body:
            application/json:
              type: getSearchResponse
              example:
                {
                  "search":
                    {
                      "id": "{268daae-5555-11e7-8af6-b7116753aa5}",
                    },
                }
        400:
          description: Invalid request, missing or incorrect search parameters.
          body:
            application/json:
              type: error
              example:
                {
                  "error": [
                    {
                      type: 4,
                      "code": 39,
                      "text": "Invalid request body",
                      "args": {},
                      "level": 1
                    }
                  ]
                }
        404:
          description: Invalid request, Incomplete data.
          body:
            application/json:
              type: error
        500:
          description: Failed to retrieve a search ID.
          body:
            application/json:
              type: error
  /ports:
    type: base-type
    description: >
      Creating a search ID for ports from the given query parameters.
    get:
      displayName: getSearchId
      description: >
        Gets a search ID for searching ports attached to this lighthouse instance.

        Any number of search query parameters can be provided to perform an
        ANDed search on the ports. The list provided is dynamic.
      queryParameters:
        json:
          description: >
            One or more json URL encoded search parameters.

            Example
            %7B%22type%22%3A1%2C%22items%22%3A%5B%7B%22datatype%22%3A4
            %2C%22type%22%3A3%2C%22oper%22%3A1%2C%22fieldname%22%3A%22
            config%3Aname%22%2C%22value%22%3A%22test%22%7D%5D%7D

            which is the URL encoded json

            {type:1,items:[{"datatype":4,type:3,"oper":1,"fieldname":"config:label","value":"test"}]}
          type: string
          required: false
          displayName: 'json'
        jb64:
          description: >
            one or more base64 encoded json search parameters.

            Ensure that any trailing = padding is URL encoded to %3D
          type: string
          required: false
          displayName: 'jb64'
        searchparameters:
          description: >
            One or more search fields.

            For example,

            config:label=\*test\*, will search for ports with labels containing test.

            Allowed operators are: =value, >value, >=value, <value, <=value,
            !value (not), \*value (ends in), value\* (starts with), \*value\*
            (contains). Reserved characters to be URl encoded, e.g. = as %3D
          type: string
          required: false
          displayName: 'search parameters*'
        operator:
          description: >
            Operator applied between all searchparameters, json and jb64
            query parameters.

            AND or OR

          default: AND
          required: false
      responses:
        200:
          description: The search ID, as defined by given parameters
          body:
            application/json:
              type: getSearchResponse
              example:
                {
                  "search":
                    {
                      "id": "{268daae-5555-11e7-8af6-b7116753aa5}",
                    },
                }
        400:
          description: Invalid request, missing or incorrect search parameters.
          body:
            application/json:
              type: error
              example:
                {
                  "error": [
                    {
                      type: 4,
                      "code": 39,
                      "text": "Invalid request body",
                      "args": {},
                      "level": 1
                    }
                  ]
                }
        404:
          description: Invalid request, Incomplete data.
          body:
            application/json:
              type: error
        500:
          description: Failed to retrieve a search ID.
          body:
            application/json:
              type: error

/services:
  description: >
    Used for working with the properties of the various services running on the system.
  /https:
    type: base-type
    description: >
      Provides access to the SSL certificate used by web services on the device.
    get:
      description: Fetch HTTPS certificate details, or a CSR file if the zip flag is set.
      queryParameters:
        zip:
          description: A flag to download the CSR instead of view the details
          type: boolean
          required: false
          default: false
      responses:
        200:
          description: Returns the certificate currently in use by the server, as well as details about any current CSR.
          body:
            application/json:
              example:
                {
                  "https": {
                    "valid_from": "Sep 21 00:39:03 2016 GMT",
                    "valid_to": "Sep 21 00:39:03 2016 GMT",
                    "common_name": "CName",
                    "country": "AU",
                    "locality": "Toowong",
                    "org_unit": "OU",
                    "email": "bob@bob.com",
                    "organization":"Internet Widgits Pty Ltd",
                    "key_length":2048,
                    "cert" : "-----BEGIN CERTIFICATE-----...-----END CERTIFICATE-----",
                    "csr" : {
                      "country": "AU",
                      "challenge_password": "aaa",
                      "common_name": "aa",
                      "state": "ee",
                      "locality": "dd",
                      "email": "bob@bob.com",
                      "key_length": 512
                    },
                    "key": "-----BEGIN PRIVATE KEY-----..."
                  }
                }
    put:
      description: Update HTTPS details. A certificate matching the CSR can be uploaded by setting the https.cert field, a CSR can be cancelled by sending through no https.csr body, and a new csr can be created by sending through a https.csr body with a csr value of "new".
      body:
        application/json:
          example:
            {
              "https": {
                "key_length":2048,
                "cert" : "-----BEGIN CERTIFICATE-----...-----END CERTIFICATE-----",
                "csr" : {
                  "country": "AU",
                  "challenge_password": "aaa",
                  "common_name": "aa",
                  "state": "ee",
                  "locality": "dd",
                  "key_length": 2048,
                  "email": "bob@bob.com"
                },
                key: "-----BEGIN PRIVATE KEY-----..."
              }
            }
      responses:
        200:
          description: >
            Returns the updated HTTPS server details
          body:
            application/json:
              example:
                {
                  "https": {
                    "valid_from": "Sep 21 00:39:03 2016 GMT",
                    "valid_to": "Sep 21 00:39:03 2016 GMT",
                    "common_name": "CName",
                    "country": "AU",
                    "locality": "Toowong",
                    "org_unit": "OU",
                    "email": "bob@bob.com",
                    "organization":"Internet Widgits Pty Ltd",
                    "key_length":2048,
                    "cert" : "-----BEGIN CERTIFICATE-----...-----END CERTIFICATE-----",
                    "csr" : {
                      "country": "AU",
                      "challenge_password": "aaa",
                      "common_name": "aa",
                      "state": "ee",
                      "locality": "dd",
                      "email": "bob@bob.com",
                      "key_length": 512
                    },
                    "key": "-----BEGIN PRIVATE KEY-----..."
                  }
                }
        500:
          description: Returns an error after the operation failed.
          body:
            application/json:
              example:
                {
                  "error": [
                    {
                      type: 2,
                      "code": 14,
                      "text":" String did not conform to the expected format.",
                      "args": {
                        "uuid": "root-1-services_https_csr_email"
                      },
                      "level":1
                    },
                    {
                      type: 1,
                      "code": 33,
                      "text": "Push command failed",
                      "args": {},
                      "level": 1
                    }
                  ]
                }
        400:
          description: Returns an error after the operation failed due to invalid user input.
          body:
            application/json:
              example:
                {
                  "error": [
                    {
                      type: 2,
                      "code": 14,
                      "text":" String did not conform to the expected format.",
                      "args": {
                        "uuid": "root-1-services_https_csr_email"
                      },
                      "level":1
                    },
                    {
                      type: 1,
                      "code": 33,
                      "text": "Push command failed",
                      "args": {},
                      "level": 1
                    }
                  ]
                }
  /ntp:
    type: base-type
    description: >
      Provides access to the NTP client configuration on the system.
    get:
      description: Fetch NTP client configuration.
      responses:
        200:
          description: Returns the current NTP configuration.
          body:
            application/json:
              example:
                {
                  "ntp": {
                    "enabled": true,
                    "servers": [
                      {
                        "id": "services_ntp_servers-0",
                        "value": "0.au.pool.ntp.org"
                      },
                      {
                        "id": "services_ntp_servers-1",
                        "value": "1.au.pool.ntp.org"
                      }
                    ],
                    "id": "services_ntp"
                  }
                }
    put:
      description: Update NTP client configuration, including enabling/disabling the NTP service.
      body:
        application/json:
          example:
            {
              "ntp": {
                "enabled": true,
                "servers": [
                  {
                    "id": "services_ntp_servers-0",
                    "value": "0.au.pool.ntp.org"
                  },
                  {
                    "id": "services_ntp_servers-1",
                    "value": "2.au.pool.ntp.org"
                  },
                  {
                    "id": null,
                    "value": "3.au.pool.ntp.org"
                  }
                ],
                "id": "services_ntp"
              }
            }
      responses:
        200:
          description: >
            Returns the updated NTP configuration.
          body:
            application/json:
              example:
                {
                  "ntp": {
                    "enabled": true,
                    "servers": [
                      {
                        "id": "services_ntp_servers-0",
                        "value": "0.au.pool.ntp.org"
                      },
                      {
                        "id": "services_ntp_servers-1",
                        "value": "2.au.pool.ntp.org"
                      },
                      {
                        "id": null,
                        "value": "3.au.pool.ntp.org"
                      }
                    ],
                    "id": "services_ntp"
                  }
                }
        500:
          description: >
            Error saving NTP configuration.
          body:
            application/json:
              example:
                {
                  "error": [
                    {
                      type: 2,
                      "code": 25,
                      "text": "'' is not a valid hostname",
                      "args": {
                        "address": "",
                        "uuid": "services_ntp_servers-0"
                      },
                      "level": 1
                    },
                    {
                      type: 1,
                      "code": 33,
                      "text": "Push command failed",
                      "args": {},
                      "level": 1
                    }
                  ]
                }
        400:
          description: >
            Returns an error after the operation failed due to invalid request.
          body:
            application/json:
              example:
                {
                  "error": [
                    {
                      type: 4,
                      "code": 40,
                      "text": "Required field 'server-1' was not provided in the request",
                      "args": {
                        "param": "server-1"
                      },
                      "level": 1
                    }
                  ]
                }

  /console_gateway:
    type: base-type
    get:
      description: Requests config parameters related to the Console Gateway service.
      responses:
        200:
          body:
            application/json:
              type: consoleGatewayResponse
              example:
                {
                  "console_gateway": { "ssh_url_delimiter": ":" }
                }
    put:
      description: Update config parameters related to the Console Gateway service.
      body:
        application/json:
          example:
                {
                  "console_gateway": { "ssh_url_delimiter": ":" }
                }
      responses:
        200:
          body:
            application/json:
              type: consoleGatewayResponse
              example:
                {
                  "console_gateway": { "ssh_url_delimiter": ":" }
                }


/tags:
  description: >
    Tags are a user definable set of name/value pairs which can be assigned to
    Lighthouse system objects like nodes.
  /node_tags:
    type: base-type
    description: >
      Provides the ability to retrieve and manipulate all
      tags associated with Lighthouse nodes.
    # Tags.getNodeTags
    get:
      queryParameters:
        per_page:
          description: Number of tags expected per page
          type: integer
          required: false
          displayName: per_page
          default: 100000
        page:
          description: The page to return (indexed from 1)
          type: integer
          required: false
          displayName: page
          default: 1
      description: >
        Returns the global tag list and associated values. Each associated
        name/value pair can be referenced from any node by using
        nodes/:id/tags/:tag_value_id.
      responses:
        200:
          body:
            application/json:
              type: getTagsListResponse
              example:
                {
                  "nodeTags": [
                    {
                      "id": "tags_node_tags-1",
                      name: "myTag",
                      values: [
                        {
                          "id": "tags_node_tags_values-1",
                          "value": "my tag value",
                        },
                        {
                          "id": "tags_node_tags_values-2",
                          "value": "new value",
                        }
                      ],
                      "rights": {
                        "delete": true,
                        "modify": true
                      }
                    },
                    {
                      "id": "tags_node_tags-2",
                      name: "myTag2",
                      values: [
                        {
                          "id": "tags_node_tags_values-3",
                          "value": "something else",
                        }
                      ],
                      "rights": {
                        "delete": true,
                        "modify": true
                      }
                    },
                    {
                      "id": "tags_node_tags-3",
                      name: "myTag3",
                      values: [
                        {
                          "id": "tags_node_tags_values-4",
                          "value": "one item"
                        }
                      ],
                      "rights": {
                        "delete": true,
                        "modify": true
                      }
                    }
                  ],
                  "meta": {
                    "total_pages": 1
                  }
                }
        400:
          description: >
            Invalid request: body is not json or does not conform to required json schema.

            Incomplete data: ??.
        404:
          body:
            application/json:
              type: error
              description: >
                No tag list found.

                Error retrieving tag list.
    post:
      description: Create a global node tag
      body:
        application/json:
          type: create_tag
          example:
            {
              "nodeTag": {
                name: "Location",
                values: [
                  {
                    "value": "USA.NewYork"
                  },
                  {
                    "value": "UK.London"
                  }
                ]
              }
            }
      responses:
        200:
          description: The newly created global tag.
          body:
            application/json:
              example:
                {
                  "nodeTag": {
                    "id": "tags_node_tags-50",
                    name: "Location",
                    values: [
                      {
                        "id": "tags_node_tags_values_90",
                        "value": "USA.NewYork"
                      },
                      {
                        "id": "tags_node_tags_values_91",
                        "value": "UK.London"
                      }
                    ]
                  }
                }
    /{tag_value_id}:
      type: base-type
      uriParameters:
        tag_value_id:
          description: Identifier for unique tag
          required: true
          displayName: tag_value_id
          example: nodes_tags-1
      put:
        description: Update tag values for the given id.
        body:
          application/json:
            type: put_tag
            example:
              {
                "nodeTag": {
                  name: "Location",
                  values: [
                    {
                      "id": "tags_node_tags_values_90",
                      "value": "USA.NewYork"
                    },
                    {
                      "id": "tags_node_tags_values_91",
                      "value": "UK.London"
                    },
                    {
                      "value": "France.Paris"
                    }
                  ]
                }
              }
        responses:
          200:
            description: The tag information was updated.
          400:
            description: >
              Invalid request: body is not json or does not conform to required json schema.

              Incomplete data: node id, or tag_value_id parameter missing.
          404:
            body:
              application/json:
                type: error
                description: >
                  Tag information with given {tag_value_id} not found.
                    example:{
                      "error": [
                        {
                          type: 5,
                          "code": 29,
                          "text": "Could not find element with UUID 'tags_node_tags-0'",
                          "args": {
                            "uuid": "tags_node_tags-0"
                          },
                          "level": 1
                        }
                      ]
                    }
      # Node.deleteNodeTag
      delete:
        description: Delete a tag by id.
        responses:
          200:
            description: The {tag_value_id} tag information was deleted.
          400:
            description: >
              Invalid request: body is not json or does not conform to required json schema.

              Incomplete data: tag_value_id parameter missing.
          404:
            body:
              application/json:
                type: error
                description: >
                  Tag information with given {tag_value_id} not found.
                example:
                  {
                    "error": [
                      {
                        type: 5,
                        "code": 29,
                        "text": "Could not find element with UUID 'nodes_tags-0'",
                        "args": {
                          "uuid": "nodes_tags-0"
                        },
                        "level": 1
                      }
                    ]
                  }

/interfaces:
  description: >
    Read and manipulate the network interfaces on the Lighthouse server.
  type: base-type
  # Interface.getList
  get:
    description: >
      Get a list of the network interfaces on the Lighthouse server.
    displayName: getInterfaces
    queryParameters:
      per_page:
        description: Number of interfaces expected per page
        type: integer
        required: false
        displayName: per_page
        default: 100000
      page:
        description: The page to return (indexed from 1)
        type: integer
        required: false
        displayName: page
        default: 1
    responses:
      200:
        body:
          application/json:
            type: getInterfaceList
            example:
              {
                "interfaces": [
                  {
                    "enabled": true,
                    description: "Default static network connection",
                    "media": "auto",
                    "netmask": "255.255.255.0",
                    "physif": "net1",
                    "role": "lan",
                    name: "default-conn-1",
                    "address": "192.168.87.156",
                    "gateway": "192.168.87.100",
                    "mode": "static",
                    "runtime_status": {
                      "status": "running",
                      "last_status_change": 1471506633,
                      "id": "system_net_conns-1"
                    },
                    "id": "system_net_conns-1"
                  },
                  {
                    "enabled": true,
                    description: "Default DHCP network connection",
                    "media": "auto",
                    "id": "system_net_conns-2",
                    "dhcp_vendor_class": "Opengear/Lighthouse",
                    "role": "lan",
                    name: "default-conn-2",
                    "mode": "dhcp",
                    "runtime_status": {
                      "status": "running",
                      "dhcp_netmask": "255.255.255.0",
                      "dhcp_gateway": "192.168.87.1",
                      "id": "system_net_conns-2",
                      "dhcp_dns": "192.168.87.1",
                      "dhcp_address": "192.168.87.200",
                      "last_status_change": 1471506160
                    },
                    "physif": "net1"
                  }
                ],
                "meta": {
                  "total_pages": 1
                }
              }
  /{id}:
    type: base-type
    uriParameters:
      id:
        description: ID of the interface to fetch
        required: true
        displayName: id
        example: system_net_conns-2
    # Interface.get
    get:
      description: Get interface information by id.
      responses:
        200:
          body:
            application/json:
              type: interfaceItem
              example:
                {
                  "interface": {
                    "enabled": true,
                    description: "Default static network connection",
                    "media": "auto",
                    "netmask": "255.255.255.0",
                    "physif": "net1",
                    "role": "lan",
                    name: "default-conn-1",
                    "address": "192.168.87.156",
                    "gateway": "192.168.87.100",
                    "mode": "static",
                    "runtime_status": {
                      "status": "running",
                      "last_status_change": 1471506633,
                      "id": "system_net_conns-1"
                    },
                    "id": "system_net_conns-1"
                  }
                }
    # Interface.put
    put:
      description: Update settings for interface {id}
      body:
        application/json:
          type: interfaceItem
          example:
            {
              "interface": {
                "enabled": true,
                "description": "Default static network connection",
                "media": "auto",
                "netmask": "255.255.255.0",
                "physif": "net1",
                "role": "lan",
                "name": "default-conn-1",
                "address": "192.168.87.156",
                "gateway": "192.168.87.100",
                "mode": "static",
              }
            }
      responses:
        200:
          description: The interface {id} settings was updated.
        400:
          description: >
            Invalid request: body is not json or does not conform to required json schema.

            Incomplete data: interface id parameter missing.
        404:
          description: >
            Interface {id} does not exist.

            Attempted to change read only fields.

            Attempted to change unknown fields.

/system:
  description: >
    System endpoints are related to configuring and accessing information about
    the Lighthouse system itself.
  /hostname:
    type: base-type
    description:
      Retrieve or change the Lighthouse system's hostname.
    get:
      description: Get the Lighthouse hostname.
      responses:
        200:
          body:
            application/json:
              type: systemHostname
              example:
                {
                  system_hostname: {
                    hostname: "Lighthouse"
                    }
                }
    put:
      description: Update the Lighthouse hostname.
      body:
        application/json:
          type: systemHostname
          example:
            {
              system_hostname: {
                hostname: "Lighthouse"
                }
            }
      responses:
        200:
          body:
            application/json:
              type: systemHostname
              example:
                { system_hostname: { hostname: "Lighthouse" } }

  /webui_session_timeout:
    type: base-type
    description: Retrieve or change the Lighthouse session timeout.
    get:
      description: Retrieve the session timeout (in minutes).
      responses:
        200:
          body:
            application/json:
              type: systemWebui
              example:
                { system_webui_session_timeout: { timeout: 20 } }
    put:
      description: Update the session timeout (in minutes).
      body:
        application/json:
          type: systemWebui
          example:
            { system_webui_session_timeout: { timeout: 20 } }

      responses:
        200:
          body:
            application/json:
              type: systemWebui
              example:
                { system_webui_session_timeout: { timeout: 20 } }

  /global_enrollment_token:
    type: base-type
    description:
      Retrieve or update the Lighthouse server's global enrollment token.
    get:
      description: Retrieve the Lighthouse's global enrollment token.
      responses:
        200:
          body:
            application/json:
              type: systemGlobalEnrollmentToken
              example:
                { system_global_enrollment_token: { token: "mySomewhatSecret" } }
    put:
      description: Update the Lighthouse's global enrollment token.
      body:
        application/json:
          type: systemGlobalEnrollmentToken
          example:
            { system_global_enrollment_token: { token: "mySomewhatSecret" } }
      responses:
        200:
          body:
            application/json:
              type: systemGlobalEnrollmentToken
              example:
                { system_global_enrollment_token: { token: "mySomewhatSecret" } }

  /manifest_link:
    type: base-type
    description: Retrieve a link to the global enrollment manifest file.
    get:
      description:
        Returns the url for downloading the manifest file in plaintext.
      responses:
        200:
          body:
            application/json:
              type: manifestLink
              example:
                {
                  system_global_manifest_link: {
                    url: "http://192.168.1.1/manifest.txt"
                  }
                }

  /timezone:
    type: base-type
    description:
      Retrieve and update the system's timezone.
    get:
      description: Retrieves the system timezone.
      responses:
        200:
          body:
            application/json:
              type: systemTimezone
              example:
                { system_timezone: { timezone: "Australia/Brisbane" } }
    put:
      description: Update the system timezone.
      body:
        application/json:
          type: systemTimezone
          example:
            { system_timezone: { timezone: "Australia/Brisbane" } }
      responses:
        200:
          body:
            application/json:
              type: systemTimezone
              example:
                { system_timezone: { timezone: "Australia/Brisbane" } }

  /external_address:
    type: base-type
    description:
      Retrieve and update the Lighthouse system's externally reachable network address.
    get:
      description: Retrieve the Lighthouse external address.
      responses:
        200:
          body:
            application/json:
              type: systemAddress
              example:
                {
                  system_external_address: {
                    external_address: " ",
                    os_default_external_address: " "
                    }
                }
    put:
      description: Update the Lighthouse external address.
      body:
        application/json:
          type: systemAddress
          example:
            {
              system_external_address: {
                external_address: " ",
                os_default_external_address: " "
                }
            }
      responses:
        200:
          body:
            application/json:
              type: systemAddress
              example:
                {
                system_external_address: {
                  external_address: " ",
                  os_default_external_address: " "
                  }
                }

  /time:
    type: base-type
    description:
      Retrieve and update the Lighthouse server's time.
    get:
      description: Retrieve the Lighthouse current time.
      responses:
        200:
          body:
            application/json:
              type: systemTime
              example:
                { time: { time: "16:22 Sep 23, 2016" } }
    put:
      description: Update the Lighthouse current time.
      body:
        application/json:
          type: systemTime
          example:
            { time: { time: "16:22 Sep 23, 2016" } }
      responses:
        200:
          body:
            application/json:
              type: systemTime
              example:
                { time: { time: "16:22 Sep 23, 2016" } }

  /config:
    type: base-type
    # System.reset
    delete:
      description: >
        Delete the configuration effectively performing a system reset.
        The Lighthouse host will reset to factory settings and reboot.
        The user will need to access the device via the console to set the
        root password before the network will be available.
      responses:
        200:
          description: >
            The factory reset process was started successfuly.

  /firmware_upgrade:
    type: base-type
    # Firmware.postFirmwareUpgrade
    post:
      description: >
        Upgrade the system firmware either by uploading a file or providing a url
        to download the file from. This endpoint will always return success if the
        firmware upgrade job was started - it occurs in the background and the state
        of which should be retrieved from the GET /system/firmware_upgrade_status
        endpoint.
        At least 'file' or 'firmware_url' are required.
      body:
        multipart/form-data:
          properties:
            file:
              description: The file to be uploaded.
              required: false
              type: file
            firmware_url:
              description: A url for the file to download.
              required: false
              type: string
            firmware_options:
              description: Options for the firmware upgrade tool.
              required: false
              type: string
      responses:
        200:
          description: The firmware upgrade process was started.
          body:
            application/json:
              type: firmwareUpgradeStatus
              example: |
                {
                  "system_firmware_upgrade_status":
                    {
                      "state": "running"
                    }
                }

  /firmware_upgrade_status:
    # Firmware.getFirmwareUpgradeStatus
    type: base-type
    get:
      description: Retrieve the status of the most recent firmware upgrade job.
      responses:
        200:
          description: The factory reset process was started successfuly.
          body:
            application/json:
              type: firmwareUpgradeStatus
              example: |
                {
                  "system_firmware_upgrade_status":
                    {
                      "state": "error",
                      "error_message": "download_error"
                    }
                }

  /entitlements:
    description:
      Retrieve entitlement information for the Lighthouse based on the licenses applied.
    type: base-type
    get:
      description: Retrieve a list of entitlements.
      responses:
        200:
          description:
            A JSON object containing entitlements information.
          body:
            application/json:
              type: object
              properties:
                entitlements:
                  type: array
                  description: A list of entitlements.
                  items:
                    schema: entitlements
              example:
                {
                  "entitlements": [
                    {
                      "id": "SKU1",
                      "contact": {
                        "name": "Jenny Bloggs",
                        "email": "jennyb@bloggs.com"
                      },
                      "features": {
                        "maintenance": 1546214400,
                        "nodes": 20
                      }
                    },
                    {
                      "id": "SKU2",
                      "contact": {
                        "name": "Joe Bloggs",
                        "email": "joeb@bloggs.com"
                      },
                      "features": {
                        "maintenance": 1546214400,
                        "nodes": 1578
                      }
                    }
                  ]
                }

  /licenses:
    description:
      Create and view licenses applied to the Lighthouse system.
    type: base-type
    get:
      description: Retrieve a list of license strings.
      responses:
        200:
          description:
            A JSON object containing raw license strings information.
          body:
            application/json:
              type: object
              properties:
                licenses:
                  type: array
                  items:
                    schema: license
              example:
                {
                  "licenses": [
                    {
                      "id": 1,
                      "raw": "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6Im1pY2hhZWxmQGZpdHp5c2l0ZS5jb20iLCJzdWIiOiJ..."
                    },
                    {
                      "id": 2,
                      "raw": "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6Im1pY2hhZWxmQGZpdHp5c2l0ZS5jb20iLCJzdWIiOiJ..."
                    }
                  ]
                }

    post:
      description: Apply a list of licenses.
      body:
        application/json:
          type: object
          properties:
            licenses:
              type: array
              items:
                schema: license
          example:
            {
              "licenses": [
                {
                  "raw": "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6Im1pY2hhZWxmQGZpdHp5c2l0ZS5jb20iLCJzdWIiOiJ..."
                },
                {
                  "raw": "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6Im1pY2hhZWxmQGZpdHp5c2l0ZS5jb20iLCJzdWIiOiJ..."
                }
              ]
            }
      responses:
        201:
          description:
            A JSON object containing the raw licenses that were just applied.
          body:
            application/json:
              type: object
              properties:
                licenses:
                  type: array
                  items:
                    schema: license
              example:
                {
                  "licenses": [
                    {
                      "id": 1,
                      "raw": "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6Im1pY2hhZWxmQGZpdHp5c2l0ZS5jb20iLCJzdWIiOiJ..."
                    },
                    {
                      "id": 2,
                      "raw": "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6Im1pY2hhZWxmQGZpdHp5c2l0ZS5jb20iLCJzdWIiOiJ..."
                    }
                  ]
                }


# Stats.node_connection_summary
/stats:
  description: >
    Retrieve statistical information about the Lighthouse deployment.
  /nodes:
    /connection_summary:
      type: base-type
      get:
        description: >
          A summary of connected, pending and disconnected nodes
        responses:
          200:
            body:
              application/json:
                type: connectionSummaryResponse
                example:
                  {
                    "connectionSummary": [
                      {
                        "status": "connected",
                        "count": 11
                      },
                      {
                        "status": "pending",
                        "count": 1
                      },
                      {
                        "status": "disconnected",
                        "count": 1
                      }
                    ]
                  }

# SupportReport.get
/support_report:
  description: >
    Obtain a report which will provide information about the state of the
    Lighthouse server. This information can be used to help analyse and
    understand the state of the system.

    The report is large and may take in the order of a minute to obtain.
  type: base-type
  # SupportReport.get
  get:
    description: Retrieve the support report data.
    responses:
      200:
        description: >
          System report was successfully generated and returned including a
          url to a corresponding zip file.
        body:
          application/json:
            type: getSupportReport
            example:
              {
                "support_report": {
                  "contents": "*** System time ***\nMon Aug 22 11:27:29 2016\n\n\n*** Firmware Version ***\n$ sysflash_info\nsysflash info\ncurrent copy name: 'root1'\ncurrent config dev: '/dev/sda6'\ncurrent root dev: '/dev/sda5'\ncurrent boot dev: '/dev/sda2'\nother (upgradable) copy name: 'root2'\nother (upgradable) config dev: '/dev/sda8'\nother (upgradable) root dev: '/dev/sda7'\nother (upgradable) boot dev: '/dev/sda3'\nboard name: 'lighthouse-vm'\nboard rev: '1.0'\ncurrent software vendor: 'opengear'\ncurrent software product: 'ironman'\ncurrent software version: '5.0.0'\ncurrent software variant: 'release'\n\n*** Uptime ***\n359140.57 715606.84\n\n*** IP Configuration ***\n$ ifconfig\nnet1      Link encap:Ethernet  HWaddr 08:00:27:d7:1c:38  \n   ",
                  "zip_file": "/api/v1/support_report?zip=1"
                }
              }

# Remote Autherntication Config
/auth:
  description: >
    Configure remote authentication, authorization, accounting (AAA) servers.
  type: base-type
  get:
    description: Retrieve information on AAA servers.
    responses:
      200:
        description: >
          A JSON object containing the AAA config is returned.
        body:
          application/json:
            example:
              {
                "auth" : {
                  "mode" : "tacacs",
                  "radiusPassword" : "hunter2",
                  "radiusAuthenticationServers" : [
                    {
                      "id" : "auth_radius_authenticationServers-2",
                      "hostname" : "192.168.250.1.2"
                    }
                  ],
                  "radiusAccountingServers" : [
                    {
                      "id" : "auth_radius_accountingServers-1",
                      "hostname" : "192.168.250.1.2"
                    }
                  ],
                  "tacacsService" : "raccess",
                  "tacacsMethod" : "pap",
                  "tacacsPassword" : "hunter2",
                  "tacacsAuthenticationServers" : [
                    {
                      "hostname" : "192.168.1.2",
                      "id" : "auth_tacacs_authenticationServers-2"
                    }
                  ],
                  "ldapAuthenticationServers" : [
                    {
                      "id" : "auth_ldap_authenticationServers-1",
                      "hostname" : "192.168.1.2"
                    }
                  ],
                  "ldapBaseDN" : "cn=Users,dc=example,dc=com",
                  "ldapBindDN" : "cn=Administrator,cn=Users,dc=example,dc=com",
                  "ldapUsernameAttribute" : "sAMAccountName",
                  "ldapBindPassword" : "hunter2"
                }
              }
  put:
    description: Update the AAA config.
    body:
      application/json:
        example:
          {
            "auth" : {
              "mode" : "radius",
              "radiusPassword" : "hunter2",
              "radiusAuthenticationServers" : [
                {
                  "id" : "auth_radius_authenticationServers-1",
                  "hostname" : "192.168.250.2"
                }
              ],
              "radiusAccountingServers" : [
                {
                  "id" : "auth_radius_accountingServers-1",
                  "hostname" : "192.168.250.2"
                }
              ],
              "tacacsAuthenticationServers":[],
              "ldapAuthenticationServers":[]
            }
          }
    responses:
      200:
        description: >
          A JSON object containing the AAA config is returned.
        body:
          application/json:
            example:
              {
                "auth" : {
                  "mode" : "radius",
                  "radiusPassword" : "hunter2",
                  "radiusAuthenticationServers" : [
                    {
                      "id" : "auth_radius_authenticationServers-1",
                      "hostname" : "192.168.250.2"
                    }
                  ],
                  "radiusAccountingServers" : [
                    {
                      "id" : "auth_radius_accountingServers-1",
                      "hostname" : "192.168.250.2"
                    }
                  ],
                  "tacacsService" : "raccess",
                  "tacacsMethod" : "pap",
                  "tacacsPassword" : "hunter2",
                  "tacacsAuthenticationServers" : [
                    {
                      "hostname" : "192.168.1.2",
                      "id" : "auth_tacacs_authenticationServers-2"
                    }
                  ],
                  "ldapAuthenticationServers" : [
                    {
                      "id" : "auth_ldap_authenticationServers-1",
                      "hostname" : "192.168.1.2"
                    }
                  ],
                  "ldapBaseDN" : "cn=Users,dc=example,dc=com",
                  "ldapBindDN" : "cn=Administrator,cn=Users,dc=example,dc=com",
                  "ldapUsernameAttribute" : "sAMAccountName",
                  "ldapBindPassword" : "hunter2"
                }
              }

/bundles:
  type: base-type
  description: >
    Creating/registering and viewing the state of console server bundles.
  # Bundle.get_bundle_list
  get:
    displayName: getBundles
    description: >
      Gets bundles attached to this lighthouse instance.


      The standard ember-data pagination fields {per_page} and {page} apply
      to this list.


      {per_page} and {page} are optional but both are to be supplied if pages
      are requested.

      A bundle response will also contain a list of tags, which represents the
      user-editable attributes assigned to this bundle.
    queryParameters:
      per_page:
        description: Number of bundles expected per page
        type: integer
        required: false
        displayName: per_page
        default: 100000
      page:
        description: The page to return (indexed from 1)
        type: integer
        required: false
        displayName: page
        default: 1
    responses:
      200:
        description: The array of bundles, either a full or as requested by parameters
        body:
          application/json:
            example:
              {
                "bundles": [
                  {
                    name: "Test Bundle 1",
                    "auto_approve": 0,
                    "id": "enrollment_bundles-1",
                    "automatic_tags": [
                      {
                        "id": "enrollment_bundles_automatic_tags-1",
                        name: "Test Tag Key 1",
                        "value": "Test Tag Value 1"
                      },
                      {
                        "id": "enrollment_bundles_automatic_tags-2",
                        name: "Test Tag Key 2",
                        "value": "Test Tag Value 2"
                      }
                    ],
                    "nodes": [],
                    "token": "abcdefghijklmnop",
                    "manifest_link": "/api/v1/bundles/enrollment_bundles-1/manifest"
                  },
                  {
                    name: "Test Bundle 2",
                    "auto_approve": 0,
                    "id": "enrollment_bundles-2",
                    "automatic_tags": [
                      {
                        "id": "enrollment_bundles_automatic_tags-3",
                        name: "Test Tag Key A",
                        "value": "Test Tag Value B"
                      }
                    ],
                    "nodes": [],
                    "token": "1234567890",
                    "manifest_link": "/api/v1/bundles/enrollment_bundles-2/manifest"
                  }
                ],
                "meta": {
                  "total_pages": 1
                }
              }
      400:
        description: Invalid request, missing or incorrect page/per_page
        body:
          application/json:
            type: error
            example:
              {
                "error": [
                  {
                    type: 4,
                    "code": 39,
                    "text": "Invalid request body",
                    "args": {},
                    "level": 1
                  }
                ]
              }
      404:
        description: Invalid request, Incomplete data, Bundle not found, Failure during retrieval of bundles
        body:
          application/json:
            type: error
      500:
        description: Failed to read bundles.
        body:
          application/json:
            type: error
  post:
    body:
      application/json:
        example:
          {
            "bundle":
              {
                "name": "PrimaryBundle",
                "auto_approve": true,
                "token": "ABCD1234567",
                "automatic_tags": [
                  {
                    "name":"Location",
                    "value":"Brisbane"
                  }
                ]
               }
          }
    displayName: addBundle
    description: >
      Add a new Bundle. The automatic_tags values must be valid as obtained using by a GET on endpoint /tags/node_tags.
    responses:
      200:
        description: Bundle added successfully.
        body:
          application/json:
            example:
              {
                "bundle": {
                  name: "Test Bundle 1",
                  "auto_approve": 0,
                  "id": "enrollment_bundles-1",
                  "automatic_tags": [
                    {
                      "id": "enrollment_bundles_automatic_tags-1",
                      name: "Test Tag Key 1",
                      "value": "Test Tag Value 1"
                    },
                    {
                      "id": "enrollment_bundles_automatic_tags-2",
                      name: "Test Tag Key 2",
                      "value": "Test Tag Value 2"
                    }
                  ],
                  "nodes": [],
                  "token": "abcdefghijklmnop"
                }
              }
      400:
        description: Invalid request, or error with supplied data
        body:
          application/json:
            example:
              {
                "error": [
                  {
                    type: 4,
                    "code": 39,
                    "text": "Invalid request body",
                    "args": {},
                    "level": 1
                  }
                ]
              }
      404:
        description: Redirect to new bundle session
        body:
          application/json:
            example:
              {"message": "Redirecting to new bundle at {redirect-url}"}
      500:
        description: Unexpected error.
        body:
          application/json:
            example:
              {
                "error": [
                  {
                    type: 2,
                    "code": 26,
                    "text": "Duplicate 'name' fields with value 'test'",
                    "args": {
                      "value": "test",
                      "uuid": "root-1-@bundles",
                      "field": "name"
                    },
                    "level": 1
                  },
                  {
                    type: 1,
                    "code": 33,
                    "text": "Push command failed",
                    "args": {},
                    "level": 1
                  }
                ]
              }

  # Bundle.get_bundle
  /{id}:
    type: base-type
    uriParameters:
      id:
        description: ID of bundle to fetch
        required: true
        displayName: id
        example: enrollment_bundles-1
    get:
      displayName: findBundleByID
      description: Find a bundle by unique ID
      responses:
        200:
          description: The requested bundle
          body:
            application/json:
              type: bundle
              example:
                {
                  "bundle": {
                    name: "Test Bundle 1",
                    "auto_approve": false,
                    "id": "enrollment_bundles-1",
                    "automatic_tags": [
                      {
                        "id": "enrollment_bundles_automatic_tags-1",
                        name: "Test Tag Key 1",
                        "value": "Test Tag Value 1"
                      },
                      {
                        "id": "enrollment_bundles_automatic_tags-2",
                        name: "Test Tag Key 2",
                        "value": "Test Tag Value 2"
                      }
                    ],
                    "nodes": [],
                    "token": "abcdefghijklmnop",
                    "manifest_link": "/api/v1/bundles/enrollment_bundles-1/manifest"
                  }
                }
        400:
          description: Invalid request, or error with supplied data
          body:
            application/json:
              example:
                {
                  "error": [
                    {
                      type: 4,
                      "code": 39,
                      "text": "Invalid request body",
                      "args": {},
                      "level": 1
                    }
                  ]
                }
        404:
          description: Bundle does not exist
      headers:
        Authorization:
          description: authorization session token
          type: string
          required: true
          displayName: Authorization
    put:
      displayName: putBundle
      description: Update a bundle
      body:
        application/json:
          example:
            {
              "bundle":
                {
                  "name":"PrimaryBundle",
                  "auto_approve":true,
                  "token":"BCDEFGHIJKLMNOPQRSTUVWXYZ123456",
                  "automatic_tags":[
                    {
                      "name":"Location",
                      "value":"Brisbane",
                    }
                  ]
                }
            }
      responses:
        200:
          description: The updated bundle
          body:
            application/json:
              type: bundle
              example:
                {
                  "bundle":
                    {
                      "name": "PrimaryBundle",
                      "auto_approve": true,
                      "id":"enrollment_bundles-3",
                      "automatic_tags": [
                        {
                          "id": "enrollment_bundles_automatic_tags-4",
                          "name": "Location",
                          "value": "Brisbane"
                        }
                      ],
                      "nodes": [],
                      "token": "BCDEFGHIJKLMNOPQRSTUVWXYZ123456",
                      "manifest_link": ""
                    }
                }
    # Bundle.get_tags
    /automatic_tags:
      type: base-type
      description: >
        Each bundle can have a list of tags associated with it. These tags are
        references to a global list of tags. Any node that enrolls against a specific
        bundle will automatically be assigned these tags and specified values at
        time of enrollment.
      # Bundle.get_tags
      get:
        displayName: getBundleTags
        description: >
          Get the list of all automatic tags for this bundle.
        responses:
          200:
            description: The list of automatic tags for the bundle
            body:
              application/json:
                example:
                  {
                    "tags": [
                      {
                        "id": "bundle_tags-1",
                        name: "myTag",
                        "value": "my tag value"
                      },
                      {
                        "id": "bundle_tags-2",
                        name: "myTag2",
                        "value": ""
                      },
                      {
                        "id": "bundle_tags-3",
                        name: "myTag3",
                        "value": "another value"
                      }
                    ]
                  }
          400:
            description: Incomplete data.
          404:
            description: Bundle does not exist.
      # Bundle.create_tag
      post:
        displayName: createBundleTag
        description: >
          Create and associate a new tag with the bundle. If the tag exists
          update or set the value. If no value is given, or the value is empty,
          the value will be set to null.
        body:
          application/json:
            example:
              {
                "tag": {
                  name: "Location",
                  "value": "New York"
                }
              }
        responses:
          200:
            body:
              application/json:
                description: Bundle with given bundle id not found.
                example:
                  {
                    "automatic_tag": {
                      "id": "bundle_tags-1",
                      name: "Location",
                      "value": "New York"
                    }
                  }
          400:
            description: >
              Invalid request: body is not json or does not conform to required json schema.

              Incomplete data: name item missing.
          404:
            body:
              application/json:
                type: error
                description: Bundle with given bundle id not found.
      /{tag_value_id}:
        type: base-type
        uriParameters:
          tag_value_id:
            description: Identifier for unique tag within given bundle
            required: true
            displayName: tag_value_id
            example: bundles_tags-1
        # Bundle.get_tag_from_bundle
        get:
          description: Retrieves a bundle's tag by id.
          responses:
            200:
              description: >
                Tag information in bundle with {id} and tag identification
                {tag_value_id} successfully retrieved.
              body:
                application/json:
                  example:
                    {
                      "automatic_tag": {
                        "id": "bundle_tags-1",
                        name: "Location",
                        "value": "New York"
                      }
                    }
            400:
              description: >
                Invalid request: body is not json or does not conform to required json schema.

                Incomplete data: bundle id, or tag_value_id parameter missing.
            404:
              body:
                application/json:
                  type: error
                  description: >
                    Bundle with given bundle {id} not found.
                    Tag information with given {tag_value_id} not found.
        # Bundle.delete_tag
        delete:
          description: Delete a bundle's tag by id.
          responses:
            200:
              description: The {tag_value_id} tag information was deleted.
            400:
              description: >
                Invalid request: body is not json or does not conform to required json schema.

                Incomplete data: bundle id, or tag_value_id parameter missing.
            404:
              body:
                application/json:
                  type: error
                  description: >
                    Bundle with given bundle {id} not found.

                    Tag information with given {tag_value_id} not found.
                  example:
                    {
                      "error": [
                        {
                          type: 5,
                          "code": 29,
                          "text": "Could not find element with UUID 'bundles_tags-0'",
                          "args": {
                            "uuid": "bundles_tags-0"
                          },
                          "level": 1
                        }
                      ]
                    }
        # Bundle.update_tag
        put:
          description: Update tag information for {bundle_tag_id} in bundle {id}
          body:
            application/json:
              example:
                {
                  "automatic_tag": {
                    name: "Location",
                    "value": "USA.NewYork"
                  }
                }
          responses:
            200:
              description: The {tag_value_id} tag information was updated.
            400:
              description: >
                Invalid request: body is not json or does not conform to required json schema.

                Incomplete data: bundle id, or tag_value_id parameter missing.
            404:
              body:
                application/json:
                  type: error
                  description: >
                    Bundle with given bundle {id} not found.

                    Tag information with given {tag_value_id} not found.
                  example:
                    {
                      "error": [
                        {
                          type: 5,
                          "code": 29,
                          "text": "Could not find element with UUID 'bundles_tags-0'",
                          "args": {
                            "uuid": "bundles_tags-0"
                          },
                          "level": 1
                        }
                      ]
                    }
    /manifest:
      type: base-type
      get:
        displayName: downloadBundleManifest
        description: Download the bundle specific manifest file
        responses:
          200:
            description: The manifest file
            body:
              text/plain:
                example:
                  address=192.168.0.1
                  bundle=bundle1
                  password=bundle1Token
          404:
            body:
              application/json:
                type: error
                description: >
                  Bundle with given bundle {id} not found.
                  Manifest information with given {bundle_id} not found.
                example:
                  {
                    "error": [
                      {
                        type: 5,
                        "code": 29,
                        "text": "Could not find element with UUID 'enrollment_bundles-1'",
                        "args": {
                          "uuid": "enrollment_bundles-1"
                        },
                        "level": 1
                      }
                    ]
                  }

/users:
  description:
    Retrieve and update user information.
  type: base-type
  get:
    description: Retrieve a list of users.
    responses:
      200:
        description:
          A JSON object containing Users Config is returned.
        body:
          application/json:
            example:
              {
                 "users": [
                    {
                       "username": "root",
                       "enabled": true,
                       "id": "users-1",
                       "groups": ["groups-1", "groups-2"],
                       "rights": {
                          "delete": true,
                          "modify": true
                        },
                    },
                    {
                       "username": "username-1",
                       "enabled": false,
                       "description": "Description- 1",
                       "id": "users-2",
                       "groups": ["groups-1", "groups-2"],
                       "rights": {
                          "delete": true,
                          "modify": true
                        },
                    }
                 ],
                 "meta": {
                    "total_pages": 1
                 }
              }
  post:
    description: Create a new User data in the config.
    body:
      application/json:
        example:
          {
             "user": {
                "username": "usernamenew",
                "password": "testPassword",
                "description": "desc",
                "enabled": true,
                "groups": ["groups-1"]
             }
          }
    responses:
      200:
          body:
            application/json:
              type: getUserResponse
              example:
                {
                  "user": {
                    "username": "usernamenew",
                    "enabled": true,
                    "description": "desc",
                    "groups": ["groups-1","groups-2"],
                    "id": "users-2",
                    "rights": {
                      "delete": true,
                      "modify": true
                    }
                  }
                }
      400:
        description: Failed to initiate user creation due to error in post body.
        body:
          application/json:
            example:
              {
                "error": [
                  {
                    type: 2,
                    "code": 12,
                    "text": "Element is below the minimum allowed length of 1 character(s)",
                    "args": {
                      "min": "1",
                      "uuid": "{60e2b0a-aafa-11e6-aca7-cb7fd0646002"
                    },
                    "level": 1
                  },
                  {
                    type: 1,
                    "code": 33,
                    "text": "Push command failed",
                    "args": {},
                    "level": 1
                  }
                ]
              }
      401:
        description: Authentication failed due to invalid session.
        body:
          application/json:
            example:
              {
                "error": [
                  {
                    type: 7,
                    "code": 42,
                    "text": "Invalid session ID",
                    "args": {},
                    "level": 1
                  }
                ]
              }
  /{id}:
    type: base-type
    # User.get
    get:
      displayName: getUser
      description: Retrieve the User information by ID.
      responses:
        200:
          description: User exists
          body:
            application/json:
              type: getUserResponse
              example:
                {
                  "user": {
                    "username": "usernamenew",
                    "enabled": true,
                    "description": "desc",
                    "id": "users-2",
                    "groups": ["groups-1","groups-2"],
                    "rights": {
                      "delete": true,
                      "modify": true
                    }
                  }
                }
        401:
          description: Authentication failed due to invalid session.
          body:
            application/json:
              example:
                {
                  "error": [
                    {
                      type: 7,
                      "code": 42,
                      "text": "Invalid session ID",
                      "args": {},
                      "level": 1
                    }
                  ]
                }
        404:
          description: User does not exist. User Not Found.
          body:
            application/json:
              example:
                {
                  "error": [
                    {
                      type: 5,
                      "code": 29,
                      "text": "Could not find element with UUID 'users-2'",
                      "args": {
                        "uuid": "users-2"
                      },
                      "level": 1
                    }
                  ]
                }
    put:
      description: Update a User data in the config.
      body:
        application/json:
          type: setUser
          example:
            {
               "user": {
                  "username": "usernamenew",
                  "password": "UpdatedPassword",
                  "description": "Updated description",
                  "groups": ["groups-1","groups-2"],
                  "enabled": true
               }
            }
      responses:
        200:
          description: User has been Updated.
          body:
            application/json:
              type: getUserResponse
              example:
                {
                  "user": {
                    "username": "usernamenew",
                    "enabled": true,
                    "description": "Updated description",
                    "groups": ["groups-1","groups-2"],
                    "id": "users-2",
                    "rights": {
                      "delete": true,
                      "modify": true
                    }
                  }
                }
        400:
          description: Invalid request
          body:
            application/json:
              example:
                {
                  "error": [
                    {
                      type: 4,
                      "code": 39,
                      "text": "Invalid request body",
                      "args": {},
                      "level": 1
                    }
                  ]
                }

    delete:
      displayName: deleteUser
      description: Delete a User
      responses:
        200:
          description: User deleted
          body:
            application/json:
              type: getUserResponse
              example:
                {
                  "user": {
                    "username": "Updatedusername",
                    "enabled": true,
                    "description": "desc",
                    "groups": ["groups-1","groups-2"],
                    "id": "users-2",
                    "rights": {
                      "delete": true,
                      "modify": true
                    }
                  }
                }
        404:
          description: User did not exist
          body:
            application/json:
              example:
                {
                  "error": [
                    {
                      type: 5,
                      "code": 29,
                      "text": "Could not find element with UUID 'users-2'",
                      "args": {
                        "uuid": "users-2"
                      },
                      "level": 1
                    }
                  ]
                }

/groups:
  description:
    Retrieve or update group information.
  type: base-type
  get:
    description: Retrieve a list of groups.
    # Group.getList
    responses:
      200:
        description:
          A JSON object containing Groups config is returned.
        body:
          application/json:
            example:
              {
                "groups": [
                  {
                    "id": "groups-1",
                    "groupname": "admin",
                    "description": "The admin group",
                    "mode": "global",
                    "global_roles": "LighthouseAdmin",
                    "members": {},
                    "rights": {
                      "delete": false,
                      "modify": true
                    }
                  },
                  {
                    "id": "groups-2",
                    "groupname": "smartgroup-admin",
                    "description": null,
                    "mode": "smart_group",
                    "smart_group_roles": "NodeAdmin",
                    "smart_group": "my_smart_group",
                    "members": {},
                    "rights": {
                      "delete": false,
                      "modify": true
                    }
                  }
                ],
                "meta": {
                  "total_pages": 1
                }
              }
  post:
    # Group.create
    description: Create a new Group in the config.
    body:
      application/json:
        schema: setGroup
        example:
          {
            "group": {
              "groupname": "my_node_group",
              "description": "to hold the node admin users",
              "mode": "smart_group",
              "smart_group_roles": "NodeAdmin",
              "smart_group": "nodes_groups_1"
            }
          }
    responses:
      201:
          body:
            application/json:
              schema: getGroupResponse
              example:
                {
                  "group": {
                    "id": "groups-4",
                    "groupname": "netgrp",
                    "mode": "smart_group",
                    "members": [],
                    "smart_group_roles": "NodeAdmin",
                    "smart_group": "my_smartgroup",
                    "rights": {
                        "modify": true,
                        "delete": true
                    }
                  }
                }
      400:
        description: Failed to initiate group creation due to error in post body.
        body:
          application/json:
            example:
              {
                "error": [
                  {
                    "type": 2,
                    "code": 26,
                    "text": "Duplicate 'groupname' fields with value 'netgrp'",
                    "args": {
                      "value": "netgrp",
                      "uuid": "root-1-@groups",
                      "field": "groupname"
                    },
                    "level": 1
                  },
                  {
                    "type": 1,
                    "code": 33,
                    "text": "Push command failed",
                    "args": {},
                    "level": 1
                  }
                ]
              }
      401:
        description: Authentication failed due to invalid session.
        body:
          application/json:
            example:
              {
                "error": [
                  {
                    "type": 7,
                    "code": 42,
                    "text": "Invalid session ID",
                    "args": {},
                    "level": 1
                  }
                ]
              }
  /{id}:
    # Group.get
    type: base-type
    get:
      displayName: getGroupResponse
      description: Retrieve the Group information by ID.
      responses:
        200:
          description: Group exists
          body:
            application/json:
              schema: getGroupResponse
              example:
                {
                  "group": {
                    "groupname": "netgrp2",
                    "id": "groups-6",
                    "mode": "global",
                    "members": [],
                    "global_roles": "NodeUser",
                    "rights": {
                      "delete": false,
                      "modify": true
                    }
                  }
                }
        401:
          description: Authentication failed due to invalid session.
          body:
            application/json:
              example:
                {
                  "error": [
                    {
                      "type": 7,
                      "code": 42,
                      "text": "Invalid session ID",
                      "args": {},
                      "level": 1
                    }
                  ]
                }
        404:
          description: Group does not exist. Group Not Found.
          body:
            application/json:
              example:
                {
                  "error": [
                    {
                      "type": 5,
                      "code": 29,
                      "text": "Could not find element with UUID 'groups-59'",
                      "args": {
                        "uuid": "groups-59"
                      },
                      "level": 1
                    }
                   ]
                }
    put:
    # Group.update
      description: Update a Group data in the config.
      body:
        application/json:
          schema: setGroup
          example:
            {
              "group": {
                "groupname": "netgrp2",
                "description": "my new description",
                "mode": "global",
                "global_roles":"NodeUser"
              }
            }
      responses:
        200:
          description: Group has been updated.
          body:
            application/json:
              schema: getGroupResponse
              example:
                {
                  "group": {
                    "groupname": "netgrp2",
                    "description": "my new description",
                    "id": "groups-6",
                    "mode": "global",
                    "members": [],
                    "global_roles": "NodeUser",
                    "rights": {
                      "delete": false,
                      "modify": true
                    }
                  }
                }
        400:
          description: Invalid request
          body:
            application/json:
              example:
                {
                  "error": [
                    {
                      "type": 4,
                      "code": 39,
                      "text": "Invalid request body",
                      "args": {},
                      "level": 1
                    }
                  ]
                }

    delete:
      displayName: deleteGroup
      description: Delete a Group
      responses:
        204:
          description: Group deleted
        404:
          description: Group did not exist
          body:
            application/json:
              example:
                {
                  "error": [
                    {
                      "type": 5,
                      "code": 29,
                      "text": "Could not find element with UUID 'groups-6'",
                      "args": {
                        "uuid": "groups-6"
                      },
                      "level": 1
                    }
                  ]
                }
