7.9 Watcher bug - Cannot save Watchers with an index set via a transform

I was going to submit this as a confirmed bug, but I figured I would check here first.
Anyone notice if I'm doing anything wrong or can reproduce my issue?
I'll submit as a bug if no response or if no one finds a mistake in my test.

Thanks!

Issue:
I cannot save a watcher with an index action where the index name is set in transform code and therefore not set in the index action explicitly. The documentation states this should be possible and it simulates without a problem, but the watcher syntax checker blocks saving.
Documentation: https://www.elastic.co/guide/en/elasticsearch/reference/current/actions-index.html#anatomy-actions-index-multi-doc-support
When I save I get the following error
Index name is required.

Code Snippet:
Below is the Watcher index action code:

PUT _watcher/watch/5726cea7-d530-49d8-b4c5-6714697b94f8
{
  "trigger": {
    "schedule": {
      "interval": "1m"
    }
  },
  "input": {
    "search": {
      "request": {
        "search_type": "query_then_fetch",
        "indices": [
          ".siem-signals*"
        ],
        "rest_total_hits_as_int": true,
        "body": {
          "query": {
            "range": {
              "@timestamp": {
                "gte": "now-90m/m",
                "lt": "now/m"
              }
            }
          }
        }
      }
    }
  },
  "condition": {
    "compare": {
      "ctx.payload.hits.total": {
        "gte": 1
      }
    }
  },
  "actions": {
    "index-updateEvents": {
      "transform": {
        "script": {
          "source": "\n            // Write each event as a seperate document\n            // This is accomplished by putting the array of events in a special variable _doc per:\n            // https://www.elastic.co/guide/en/watcher/current/actions.html#anatomy-actions-index-multi-doc-support\n            // This will essentially update the current event with the new values in related.alerts\n            // related.alert is currently a single value and not an array, so it will overwrite existing values\n            \n            //Debug.explain(ctx.payload.+_value);\n            // _value = [{_index=.siem-signals-default-000003, foo=bar, _id=36edb86fe3a8e3f73e87c4b357a87fd674322313efa40659e56aaaff71225afb}]\n            \n            return  ['_doc': ctx.payload._value];\n          ",
          "lang": "painless"
        }
      },
      "index": {}
    }
  },
  "transform": {
    "script": {
      "source": "\n      \n      \n        // An alerts and events array will hold the objects we want to return with this watcher\n        def results = new ArrayList();\n        \n        //  Loop over results. this could be a map as well\n        for (hit in ctx.payload.hits.hits) {\n            def updateEvent = new HashMap();\n            // Add our new value\n            updateEvent.foo = \"bar\";\n            \n            // We want to update an existing document with this new value {foo:bar}\n            // According to: https://www.elastic.co/guide/en/elasticsearch/reference/current/actions-index.html#anatomy-actions-index-multi-doc-support\n            // this can be achieved by resulting the object as _doc and setting _id and _index to match the original document\n            \n            // Get the IDand set it into our new object so when we write the document it updates an existing document\n            updateEvent._id = hit._id;\n            \n            // Get the index and set it on our new object so when we write the document it updates an existing document in an existing index\n            updateEvent._index = hit._index;\n \n            results.add(updateEvent);\n        }\n        \n        //Debug.explain(results);\n        return results;\n      ",
      "lang": "painless"
    }
  },
  "metadata": {
    "xpack": {
      "type": "json"
    },
    "name": "[Jessvin] Index Update Bug"
  }
}

Full Example Watcher POST:

PUT _watcher/watch/5726cea7-d530-49d8-b4c5-6714697b94f8
{
  "trigger": {
    "schedule": {
      "interval": "1m"
    }
  },
  "input": {
    "search": {
      "request": {
        "search_type": "query_then_fetch",
        "indices": [
          ".siem-signals*"
        ],
        "rest_total_hits_as_int": true,
        "body": {
          "query": {
            "range": {
              "@timestamp": {
                "gte": "now-90m/m",
                "lt": "now/m"
              }
            }
          }
        }
      }
    }
  },
  "condition": {
    "compare": {
      "ctx.payload.hits.total": {
        "gte": 1
      }
    }
  },
  "actions": {
    "index-updateEvents": {
      "transform": {
        "script": {
          "source": "\n            // Write each event as a seperate document\n            // This is accomplished by putting the array of events in a special variable _doc per:\n            // https://www.elastic.co/guide/en/watcher/current/actions.html#anatomy-actions-index-multi-doc-support\n            // This will essentially update the current event with the new values in related.alerts\n            // related.alert is currently a single value and not an array, so it will overwrite existing values\n            \n            //Debug.explain(ctx.payload.+_value);\n            // _value = [{_index=.siem-signals-default-000003, foo=bar, _id=36edb86fe3a8e3f73e87c4b357a87fd674322313efa40659e56aaaff71225afb}]\n            \n            return  ['_doc': ctx.payload._value];\n          ",
          "lang": "painless"
        }
      },
      "index": {}
    }
  },
  "transform": {
    "script": {
      "source": "\n      \n      \n        // An alerts and events array will hold the objects we want to return with this watcher\n        def results = new ArrayList();\n        \n        //  Loop over results. this could be a map as well\n        for (hit in ctx.payload.hits.hits) {\n            def updateEvent = new HashMap();\n            // Add our new value\n            updateEvent.foo = \"bar\";\n            \n            // We want to update an existing document with this new value {foo:bar}\n            // According to: https://www.elastic.co/guide/en/elasticsearch/reference/current/actions-index.html#anatomy-actions-index-multi-doc-support\n            // this can be achieved by resulting the object as _doc and setting _id and _index to match the original document\n            \n            // Get the IDand set it into our new object so when we write the document it updates an existing document\n            updateEvent._id = hit._id;\n            \n            // Get the index and set it on our new object so when we write the document it updates an existing document in an existing index\n            updateEvent._index = hit._index;\n \n            results.add(updateEvent);\n        }\n        \n        //Debug.explain(results);\n        return results;\n      ",
      "lang": "painless"
    }
  },
  "metadata": {
    "xpack": {
      "type": "json"
    },
    "name": "[Jessvin] Index Update Bug"
  }
}

This was a bug and fixed in 7.9.1 according to release notes.

1 Like