diff --git a/README.md b/README.md index 15d801a6a..b224b4683 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ This repository contains: Please use this repository to discuss any changes to the specification, either my making issues or PRs to the specification. -# Specification Format +# Specification Format An Elastic Package specification describes: 1. the folder structure of packages and expected files within these folders; and diff --git a/code/go/Makefile b/code/go/Makefile index c83c39047..a28801e08 100644 --- a/code/go/Makefile +++ b/code/go/Makefile @@ -15,4 +15,4 @@ check: # Runs tests test: - @go test -v ./... + @go test -v ./... \ No newline at end of file diff --git a/code/go/go.mod b/code/go/go.mod index e7f73cd7c..ec63bc157 100644 --- a/code/go/go.mod +++ b/code/go/go.mod @@ -3,6 +3,9 @@ module github.com/elastic/package-spec/code/go go 1.14 require ( + github.com/Masterminds/semver/v3 v3.1.0 + github.com/pkg/errors v0.9.1 github.com/rakyll/statik v0.1.7 github.com/stretchr/testify v1.6.1 + gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c ) diff --git a/code/go/go.sum b/code/go/go.sum index 59a7d7a81..b3cbf26e7 100644 --- a/code/go/go.sum +++ b/code/go/go.sum @@ -1,5 +1,9 @@ +github.com/Masterminds/semver/v3 v3.1.0 h1:Y2lUDsFKVRSYGojLJ1yLxSXdMmMYTYls0rCvoqmMUQk= +github.com/Masterminds/semver/v3 v3.1.0/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= diff --git a/code/go/internal/spec/statik.go b/code/go/internal/spec/statik.go index 2e18cdacc..17c3ce14c 100644 --- a/code/go/internal/spec/statik.go +++ b/code/go/internal/spec/statik.go @@ -8,7 +8,7 @@ import ( func init() { - data := "PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x00 \x001/changelog.spec.ymlUT\x05\x00\x01\x80Cm8\x9cT\xdfo\x94@\x10~\xe7\xaf\x98\x1c&\xd5(\xd0F\x8d\x91\xb7\xc6\xd6\x1as\xb6\x8d\xfab\xfc\x91,0\xc0\x94ew\xdd\x1dzw\xff\xbd\x81=\xee\xb8\x1f\xad\xd1y!\xf3\xcd\xb7\xc37\xdf2\x84a\x10\x86p\x81.\xb7\x94\xa1\x03\xae\x11\x9c\xc1\x9cJ\xca\x05\x93VPj;\xa0F\xe4\x8d\xa8\xf0\xc4\xc1\xbb\x0f\xe7\xd7W\x97\xf3\x9b+(Ib\x10\x86A\x7f\"\x0d\x00B\xb8\xbcG\xbb\xe2\x9aT\x05\x9d*\xd0B\x8d\x16\xa1\xd4R\xea\x85\x83\x8f_n\xae\xc1\xe55\xb6\x02\x9e\xd6\xcc\xc6\xa5Ir\xe7\xb4\x8a<\x18k[%\xcf^\xc0\xc2\x123*\x10\x0e\xbe\x9d\x7f\x9a\x0f\x1a,\x8aBd$\x89W\x01\x00\xaf\x0c\xa6 \xac\x15}F\x8c\xad\xeb\x05\x8c\x05\x9d\xdda\xce\x03 \x8a\x82\xfaA\x84\xbc\xb5\xda\xa0eB\x97B)\xa4\xc3\xa1n\xb6\xe8\x90\x03\xdc\xa3u\xa4\xd5\x98\x02\x14\x83=\xa6\xef\x92\xc2\xad\xf7ad\xc5\x1b\x96\x7f\xb3cK\xaa\xda\x80F0\xa3U)\x9c\xfc\xfa~\x1a\xbd\xfd\xf9\xfcG\xbc\xfb|r\xb2\xe1\xe2R\xb4Fnu\x00D0;\x8bO\xe3W\xb35\x92\xd7BUS\xc2\x8e\xb299\x06]\x8e, 5^\xdaCbG\xff|L\\\x9c\x92&^\xfa\xf8\x9b\xa3>\x0e}\xf51\x95\xbcS\xd8\x9b\xe6b\x9bl\x87\x8a\xf7N\x1c\xf5\xdc\xc7\xa1\x9b>\"\x98\xbd\xa7%dV7\xa8\x80\xb15R0\xce\x82\x83\xb6\x8f\x89\xfb\xba2\xf8\x7f\xaaT\xd7\x1eQ\x94Y\x14\x0d\xa9*\xf2\x0dgG\x18]U\xd2\xf2H\x01U-T\x8e-*>Rm\x94^\xa8\x88\x9c\xeb\xf6\x9aJR\xcd\xa3#\xceI5\xc0\x1a\x86\xb3\xa0-\xdc~^\x13\xb2~\xbb\xbd\xd0\xfe\x1b+\x90\x05\xc9\x7f\xf1\xe0\xe1\x9b\x19\xff \x15q\xddeq\xae\xdb\x04\xa5pLy\x92\xa1`\x97\x0cj\\r\xf6\xf2\xf5\xe9\x9b\xe9@\x16\x7fwd\xb1\x98\xf6\x8c\xa6\x03\xed\xe0\xbd\xb8\x1d\xa0w#8\xec\x13\x8d\x8b\xb3\xce\xd6\x9b\xf5'\x00\x00\xff\xffPK\x07\x08\xeeO\xccS\xf8\x01\x00\x005\x05\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00 \x001/changelog.ymlUT\x05\x00\x01\x80Cm8l\x8f\xb1N\x031\x10D{\x7f\xc5H\xae\xcfNZ\xf7\x14i\x80\"?\xb08{\xe7U\x1c\xdb\xca\xee!\xf1\xf7(\x864\x88v5\xfbf\x9e\xf7\xce{\x9c\x8b(V\xa9\x8cK\xcf\xfb\x8d\x9b)r\xa1\xb6\xb1B\x1a\xac0\x06\xe5+m\x0c\x1d\x9ce\x95L&\xbd\x05\x9c\x0c\xa2x};\x83\xfe\x8fLlp\xde\xbb\x05\x9f|W\xe9-\xe1\x18\x0e\xe1\xb0P\x1d\x85\x8e\x0e\xcf\xaa\xe4\x80\x05\x17\xd6|\x97a3xjbB\xf5\xf9\x89\xbe\xce1/\x95\xd4$\xe3\xfdO\xe3\xdc\xe4\x00\xc0\xbe\x06'p+\xd42?\x84\xe6\xb5J\xbb&\x14\xb3\xa1)\xc6M\xac\xec\x1f!\xf7[\xe4\x1f`\xfcUX\x1e\xc08\xf6Z5\x1e\xddw\x00\x00\x00\xff\xffPK\x07\x08ms,a\xbc\x00\x00\x00$\x01\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00 \x001/dataset/fields/fields.spec.ymlUT\x05\x00\x01\x80Cm8\x84T\xc1n\xd40\x10\xbd\xe7+\x9e\x1a$@\xea\xd2{nH\xe5\x82\xa0 \x95\x0b\xa7\xd5$\x9e$.^O\x18O\xba\xcd\xdf\xa38e\xb3\x8dV\xda[\xde\x9by\xe3g\x8f^\xca\xb2(K\xdcsj\xd4\xd7\x9c`=#\x0d\xdc\xf8\xd67d^\"ZQ\x10\x1c\x19%\xb6\xf7 \xcf\xa4^\xc6\x84\xd6spp\xdc\xfa\xe8\x97F\x1f8\x15eY\xcc\xfa\xaa\x00J|yf\x9d\xac\xf7\xb1\xc3\x18\x1d+zVF+!\xc81\xe1\xeb\xe3\x8f\x07\xa4\xa6\xe7\x03\xe1Co6\xa4\xea\xee\xee)I\xdc-\xe4'\xd1\xee\xee\xe3-\x8e\xea\xcd8\x82\x12~\x7f\xfe\xfe-;R&G\xb5\x0f\xde\xa6\x02\xb0i\xe0\nR?qc\x05@\xceeK\x14~\xaa\x0c\xac\xe69U0\x1d\xb9\x00\x86\x95*\x00 \xd2\x81\x97/\xc0\xe5w\x18fm\x85\x07:0\xa4].\xfa\xda\xb0\x1c\x94L}\xec2e\xde\xc2e\xf9\xaf\xb9r]\x9f\x89K\xfa{2\x9a\xabWG\x00\x1c\xc7\xc3\x7f\x0f;4\x12\x93Q\xb4\xfd\x1f\x9e\x8e\xa2\xeeT0~\xb1\x13\xd8\x16\x83\x9c\xc6\xed\xe0\xa3q\xc7z\xc2\xa9\x17]\xa5\xf5d|\x02N\xc6:\xac\xb0\x0dBkgO\xa1\xdd\xbf\xa5RC\x81\xdd\x86tt>\x91\x8c\xf7\x91\xa2\xa4\xf5D\x91\xc0\x14W\xec#\xe9\xb4\xb5\xbbW\x8a\xdd\xc6\xca\x86\x9bo\xb9\xa1\x96\x0bl\xc9\xd9\xc3[\xca\x0f\x1b\xa2S\x19\x87\x8c\xce\xf7vi\x95\x8f\xf3\xf3\x9dSWw\x9a\x8b\xe9\xf2\xb0\xb1\xde-\xe5[\x1c{\x8eY\x0c\x9f\xce\xfc\x00\xef\x94\xdb\n7\xe5MFe\x8e\xdak\xaa\x90\xa6h\xf4\x92S4\x88\x8f6\xa7\xd3$'_El\xf6\x96\xff\x02\xb9\xbb\x00\x94\xff\x8e^\xd9\xcdnv9.\xf9c>\xb6\xf8\x17\x00\x00\xff\xffPK\x07\x08W\xf9\xc8\xba\xbc\x01\x00\x00?\x04\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x19\x00 \x001/dataset/fields/spec.ymlUT\x05\x00\x01\x80Cm84\x8eA\n\xc20\x10E\xf79\xc5'\x08]HZ\xb7\xe6\x00\xee\xdc\xb9\xd3\"!\x99\xc0@\x9a\xc6t\n\xd6\xd3K\x8a\xae\x06\x1e\xcc\xfbo)\xe4\xad2\x08\xb4\xf8\xcaEx\xce\x16\x17\xa6\x14\x16\x04\x8a\x9c\xb9!\x05\xc8V\xc8\"r\"\x05\x14'B5[twg>'s\x1e\x7f\xf79\x1e\xff\xe4\xd1oS\xea\x14P\xe9\xb5r\xa5`!um\xdf~\xceBY\xae\x14\xd8\xddv\xadv\xa5$\xf6\xaem\x0do\xb3\xb9)i\x05\x1c*E\x0b\xdd\x0fq\x0f\xea[l\xb3j\xf5\x0d\x00\x00\xff\xffPK\x07\x08\xe8.L\x93\x92\x00\x00\x00\xb7\x00\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1b\x00 \x001/dataset/manifest.spec.ymlUT\x05\x00\x01\x80Cm8\xccV_\x8f\xdb6\x0c\x7f\xcf\xa7 .\x0fk\x81%i\xb7\x87\x01y\x19\xba^\x81\xdd\xb0v\x052l\xd8\xd3A\xb1\xe9X\x85,y\"}w\xf9\xf6\x83$;\x91m9\xce\xed6\xa0|\xb2)\x8a\xe4\x8f\xe2\xbf\xe5r\xb1\\\xc2-Rf\xe5\x1e \xb8D\xa0\x1a3Y\xc8L\xb04\x1a\ncA@.X\x10\xf27\x04\x95\xd0\xb2@\xe2\xf5\xb1RPH\x85\x8b\xe5r\xe1\xael\x17\x00K\xf8\xf0\x80\xf6\xc8\xa5\xd4\x07ht\x8e\x16J\xb4\x08\x85Q\xca<\x12\xfc\xb2\xfb\xed\x13PVb%\xe0U\xc9\\\xd3v\xb3\xf9BF\xaf\x02sm\xeca\xf3\xfa[x\xb4\x92\x195\x08\x82\xbf\xde}\xfc\xd5;aQ\xe4b/\x95\xe4\xe3\x02\x80\x8f5n\xc1\xec\xbf`\xc6\x0b\x00\x91\xe7\xd2\xb9+\xd4gkj\xb4,\x91\xb6P\x08E\xb8\x00\xa8\xcf\xbc\x05\x00\x80\x16\x15\x86/\x80\xdcc\xaf\xdd\xe5-|\x12\x15\x82):\xb8\xadH\xb0El\xa5>x\x16KVi\x05\xbf\xbb\x93H\xc3zJ\x05\x00>\x89\xaaV\x9dK\x00+x\xf7\xe7\x0e\xf6R)\x17\xbc\n\xd9\xca\x8c\xfc\x99E\x85\x82\xd2\x06w\xdc\xc6\xe4J\xa3\xba\xa9\xce\x06\xf1\xa9F++\xd4,\xd4\x89\xb9G\x16\x93.\x9e\x0e\xbd\xeed\x04\x8e\xf55!\x1c\xba\x12\xe3u\xff\xca\x1ch\xd2\x8bX\x98\xd8\xa2\xa8h\"8\xfe\x0cLQ\xa0\xc5\x1c\xf6\xc7t\x88\x84\xb5\xe2\xd8r$\xe3Y\xdb(\xcf\x02]\xce\xb6@\xc3\x9ck\xb5\xeb\xba\xe1\x98\x91\x0cM\xa0!\xee@+\x10\x8f\xb4\xe9\x87\xab;\xa1\xef\x07\x0c_\x9fgF/o[\xd6s\xad\xbb$\xfd)\x91\xa4\x81\xe2\xf0\xbf\xcc\xce{\xa3\x14f\x0b.\x81\x0d|P\x82Xf\x84\xc2f%H\x9d\xe3\xd3I\x89o3!\x9f\xd67\xd7x\xff ,]0z\xe7\x1e\xdb I\xb1WH\xeb\x84\xca8\xf3\x02\x0d\xf2/\x16\x1eda\xa0kr1P:#\x03\xc5\x1d1\xa6\x1e\x9e?Z$^z\x9d\x90\x9e|\xe4@\xe9\xa7\x0e\xb4\x82\xd2\x10\xd3\xe8$\xee31\xf5\x1c\xbb\x15,\xbc\xa4k<]\xbc\xff\x8d\x83QK\x8ai\x05\x8cO\xc3\xc0\x87\x83\xa3\xa8\xd4\xb3\xa1&\xb5%\x8a3Pz\xc0\xbc\x04\xe6E\xe7~N\xbe\xc3da\x8f\x8faW\x1a\xcb1\xeb\x7f\xf5\xf7\xc6;\xecLH\xcdx\xb0am!\xb4\x0f2CW\xf2\x99\xd1\xdau\x1267#\x05U\xa3X\xce\x02z/\xf4\xc9\x7f\xa7\x8e\x85\xd4\xe1j\xad\x10\x1e\x84j\x90~\x9c\xc4\xb57F\xa1\xd0I#\x85h\x14\xa7\xcb\x15f\x91\xb3m\xc6\x97,\xfe\xddH\x8b\xf9,\xa8;:c\xea.}- \xa84\x8f\xf7\x0d\xa1\x9dE\xb1+M\xa3r\xe0RFp\xf6\xe85h\xf7\xfan\xa3u\x9a\xfc\xf0\x0f\xae\xbe\x08e\xd2\xdf9\x90\xe9\xd0t:\xe70\xde\x06\xb9\x90h\xaf\xe8\xb5\x9fS\x1d\xd8I,\xe3\xd1\x12(9`\xe2\x8b\x93ux\x19\xa5\xafE\xb7\xd3o7\x9b\xb7\xdf\xfd\xb0~\xb3~\xb3~;\xac\xb8\xa9\xec\\\xf9\x992b\xfa\x9e>\xa2H\x0c\xb5\x8bA~i\x08S;\xd2;\xd9\xfe\xeb\xa7\xdf}\xec\xe6*\xf4\xe7\xe8?\xb2\x12q\xfd\x82\xe7\xff1\xde4:E=\xd7\xfa\xbb\x88 B\xd75\x0b\xa9\xfd@\xefzpb\xf6\xcf\xcf\xfc\xd4\xac\xf7\xcb\xce}\xb7\xec\xc4!\x1bl-\xbd\x9d\xe8\xecPtab\x1f\x99\xf7\x0b.\xec!\x84\xccR\x1fF\xc9\xd5\xaf\xf7V\x08\x08\xb3n\xb4\xf4\xb7\xb8\xc1\xed\xc9\xd5\xa9\x12u=k\xeec+\xf4rsR\x1f\x90\xf8\xbe\x965*\xa9G\x83\xfeBb\x84\x9b\xd0\xdd<\xc5\xe9Z\xcb\xd7\xbe\x0b\xfc\x17;\xe2\xdd\xc0\xd9DY\xc3\xe5N3\xdb\"b\x81\xae,\xff \x00\x00\xff\xffPK\x07\x08\xb9\xb2H\x06\xb5\x03\x00\x00\xc8\x10\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x00 \x001/dataset/spec.ymlUT\x05\x00\x01\x80Cm8\x9c\x94O\x8f\xd40\x0c\xc5\xef\xfd\x14V\x854\x07\xd4\x198\x92\x1b\x12 q\x00.\xdc\xd0je\x12w\xd6R\x9a\x86\xd8\x95\x18>=\xea\x9f\xcct\xb7\x85v\xf74\x9a\xf8=\xfb'\xbf\xa4\x12\xc9\x9a\xa2\x02Gb\x13G\xe56\x18\xf8\xd4zG l\x1b\x149p8\x03\x82p8{\x02\x87\x8aB\n\x8ej\x0e\xdc\xcb\x0b\x00\xbdD2P\x0f\xae\x02 \xa2*\xa5`\xe0\xf0\x03\xab?o\xaaww\xd3\xef\xfd\xdd\xeb|r(\x00\x1a\x0e\xdf\xac\xed\x12\x05Kb\xe0m\x01\xc3H\n*\xa6\x00x\x02\xf5>\xcf>\x084\x18\xb8&Q\xa8\xd9S\x01pE\xc8\x7f\xa7>_\xc81~\x1fJ%\xc6\xe8\xd9b\xdf\xec\xf4\xbb\xba`\xe3\xcbA\x1a\xb0\xe9\xcb\xb9\xe5\xf1\x92\x0b\x89~u\x9c\xc8\x19\xd0\xd4\x8dm_%\xaa\x0d\x94\xc7\xd3U\xdd\xef/[6\xb7X3y7[\x9d\xcc\xd1\xf3\xf62\xd1 \x96M\x92Qvz\x16\x07\x9e)h\x95\xc8\xa3\xd2n\x9e\xc1\xf4/\x9cyn{\x01@4\x116\x8b\xf9+\x04\x99atLG+\x18OA\x96\x97h}\xf0$^\\\xa3\xdb\xe4r\xf4\xf4+>>\xfc\x94\xf2Z\xde\xbci\x8f\xd4\x0b\xe6\xcdU}\xf4(\xcaV\x08\x93}\x00\x14!\xfdoL4\xd7\xbf$\x9b\xc7\x03?\x87s\xff\xce\xbe\xb6\x8e r$\xcf\x81\x9e\x93\x18\x0f\xfe\xfbl\xdd\x97\xd2\x07\xaa\xb1\xf3:\x99\xd7\xe6\xee\x08\xcc\x8dMn\xef\x19\xf6\xa4u\xfb.\xc02\xae\xbf\x01\x00\x00\xff\xffPK\x07\x08\xa7\xe6\xb9\xa6z\x01\x00\x00-\x05\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00 \x001/kibana/spec.ymlUT\x05\x00\x01\x80Cm8\xcc\x90?O\xc30\x10\xc5\xf7~\x8a\xa7,\x1d\x10e\xf7\xc6\xc2\x82\xd8\x18\x91\xd05\xbe\xd2C\xce\xd9\xf8\xdc\n\xf8\xf4(nhE\xe9\x10\"!e\xcc\xf9\xfd\xc9\xfb\x01\x96\xb8u\x0b\xe0\x1a\x9e\xad\xcd\x92\x8aDu\xb8\x8b\xc1sF\x1b\xb5\x90\xa8\xe8\x0b\xeeeMJ\xf0d\xdbu\xa4\xecAf\\l\x01\x00\xe5#\xb1\xc3\xa6z\xeaA\xa9cw\xd2\xd6[\xe6\xb7\x9dd\xf6\x0e\x1b\n\xc6\xf5\xd6\xe7\xb3\x16s\xf5\xeb\xec\x1fn\xcf\xcb\xb0\x91p\xf0\x1d+O\x87!\xea\x81\xbd\xd0c}l(\xa5 -\xf5i7\xaf\x16\xb5\x19\xa4\x89J\xe1\xac\x0e\xcb\xd5\xd5\xd3\xaa\x7fY\xfe\x81\xc0^lGA>k\xee\x08\n?\xf4SI\\(\x9d\x07\x0d\xa3={\x18Sn\xb7#`\x1c\x84S)\xfc.\x9b\x07\x84\x8e\xd2\x88\xed\x1d\xa5\xa9\xc3\x8f\x05\xf3\xd8+\xea\xf9\xfd;c\xc4\xf2\xa6\x1a\x9e\x07C3\x91\x82^\xea\xfdO _\x01\x00\x00\xff\xffPK\x07\x08\xcc\x18\xa2\x06\xf4\x00\x00\x00\x1e\x05\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x13\x00 \x001/manifest.spec.ymlUT\x05\x00\x01\x80Cm8\xccXmo[\xbb\x0d\xfe\xee_A\xd8\x05\x92,\xb3\x9d\xb4\x18\x86\x18\xd8\x82\xa0-\xd6niW,\xfd\xb2\xdb\xf6\x1a\xb2L\x1f\xab\xd1\x91NE\x1e;\xce\xaf\xbf8\xef:o\x8e\x91\xa4\xb8\xd5'\x8b\xa2\xc5\x87\xd4C\x8a:\xa3\xd1`4\x827H\xd2\xa9\x05\x12\xf0\x1a\x81\"\x94j\xa5\xa4`e\x0d\xac\xacK\xa5\x91\x90\xb7\"\xc0#\x82P(\x03\xa10j\x85\xc4\x93]\xa8a\xa54\x0eF\xa3A\xf2\xcf\xd9\x00`\x04o7\xe8v\xbcV&\x80\xd8,\xd1\xc1\x1a\x1d\xc2\xcajm\xb7\x04\xff\xbe\xf9\xefG \xb9\xc6P\xc0\xf1\x9a9\xa2\xd9t\xfa\x9d\xac\x19g\xc2\x89u\xc1\xf4\xe4\xaf\xb0u\x8a\x19\x0d\x08\x82\xff_}\xb8N\xb18\x14K\xb1PZ\xf1n\x00\xc0\xbb\x08g`\x17\xdfQ\xf2\x00@,\x97*A-\xf4'g#t\xac\x90f\xb0\x12\x9ap\x00\x10U\xb2\x01\x00$\xdb\x85\x82\xe7\x1bt\xa4\xac\xc9d\x00\xcb4\x18Q\xb2\xcd\x0c>\xaf\x11\xf2u\xb0+?\x10\xed0\x85\x82!&\\\xc2b\x07\xbcVThN\xf2\x8d3\xac\xc4N\x99 \x17E\x82\x19\x9d\x99\xc1\xd1\xef\xc7_\xce\xc6\x17\xdfNO\xbeN\xda\xbf\x8e/g\xe3\xf4\xf7\xd5\xf871\xbe\x1f\x7f;=\xbe\x9c}\x9d\xd4$'\x7f99\xb9L\xc4\xa7u\xf1\xe5\x8b\xa3\xdc\x18\xde\x890\xd2\x85\xf3\x00c\x18\x9eO\xce&g\xc3tnD\x88\xbd!H\x16\x1b\xfe\x1f\xe4\xd5\x171\xbe?\x1b_\xcc\xbf\x9d\xf6\x83\x10\x91\x90kL\xa7\xacX\xf7\x83HW\x0fG\xd1\xb6tUY\xf27\xef\xb2w\x05\xda\x9a\x00\x9d/}\xbaixo\x18\x03\x972&]z\x1c\xf5\x0e\n\xfd\x9fC\xa8\xb3\xc9yA(\xad$\x1a\xea?\xce|=\xaf\x0f\xdb\xb5\x92\xebZ~)\x82\x05&\x05\xc4\xa1FA\xb8\xdc\x17p\x13\x87\x15\x8a\x85 %K\xb3+\x11k\x9e\xd5\x84m\xe0\xd5j\xba{/\x05wQ\xca\xc0\x87\x0f\xa2\x8eH5\xce\xbd\x0bBS'w\xbb\x17\x0bq^\x06\x0fgG\x1d\x14\xdeE\xe8T\x88\x86\x85\xae\x02\x81,\xcaI z\xd1\xb6\xfe,\x05c`\x9d\xaa\x94j\x88_\x97\xcb\xc0\xb6<\xed\xaaH\xc2\x02\x93\x8c\xa3:z\xe1\x9c\xd8\xe5\x12\xc5\x18\x96{w\xbaWw0\xad-[\xf2g\xf7\xb1Co.\xb5\x8d\x97\xfe\xdc\x9a\x95\n\xe6\xa10\"\xc0\xc4\xb5\xfa\x1a\x0be\xd0\xf9\x1bJ\x17\xfa\xb3\x98\xd8\xfa\x82\xa5`Alk6Q\x0bb%\xe7\xc4B\xdez\xf2\xc0\xda@\xe3\xbc \xe96^\xa03\xc8\xe8\x9b\xd5\xc2\x04\xb1\x08j\xb2\x10\x89D\x80\xf3\x1f1\xc6\xbe\xbd\xd0\x1a\xc5\xb6\x16\xa41\x18\xe4\xadu\xbeyc\xb9\xbc\xcb<\xb1\xa59\xed\x88\xd1\xf7*rv\x19KV\x9b\xec\x06.\xc4\x842v\x0dQ\x1cE\xd6\xf9Qd%o\x91\xeb`\xf2\x1a7O\"\xec\xac\xf6V\xb6\xb8\xa8N\xb6\xc1@\x7f]Z\x93]\xfb=\xd4\xb3\x86\xd8 e\x98\x1a\xc5\xc6\xa3\x9f\x14\x06\x16\x08\xca\x10\x0b\xad\x9b\xc5\xa6l0\x92\xb1\xa7\xc9\xc8\x14r\xbdf\xbb\x91\x8c[\xb5\x10FT\xf3\x06\xd4\xff\xa4\xcbEH\x08\xa4\x0d#\xc1j\xa1\x11\xb6\x8a\xd7\x9dmE\x0f\xca\x07\x90zZ]8\xa1}9\x15\xa33\xf1\xb2\xd1>\xa4l\x8ca\xf8\xcf\x7f\xfc}rQ\\\x0dJ\xf6\x9d\xd5\xb5\"N\xeaY\xaa\x91\xf6{{\x9b\xa9\x07\xebC#$\x87\x04\xa4;\x1c\xe4d\xdd\xab\x1a\xec\xff\xa1\x16\xac6I\x0dNN\xc9\xa6\xf58\xf1\xe1\x88@\x85 \xbf\x92\x16yR\xdb\xa07\x8e\xddQ\x1c\xc3p\xaa\xc2`\xaam`\xe7Y\xcf4\xa1M0\xf4Y\xe0\xb7O\xd9\xa8\xdf\x1aE\x03\x95 {*\x98\xbc\xa3\xb9\xb6\x81\xf51\x90\xba\xdf\x07\xe1F\xdd\x97-\xdcs\xa0x\xf5\xf2\xee\xd5\xcba3\x13\xfa\xed\x7fx\xff\xe1my\x8b\x17 \x9e\xf1\x88\xd2\x9d\xa6\xb4 N\xefB]\xe1r\xf8#V\x0e\x97~\xf5\"\x975\x1c$\x1d\xa2\xa1\xb5\xe5\xfd)\xe1\xe9%\xd3\xbcT\x08\"d\x02\xe9P\xf0CO\x8f_:[\x12\xf7L\xea\xde\xf3\xe7L\x96.\xf3\xe4\xa5\xb9\x9c\x13\xba\x0d\xba\xe4\x02\xe6\x98&\x91y\\\nU\xa7\xf1T\x84y\"\xbd\xfb\xfc\xf9\xd3\x1b\xb8I\xc1\xc1M\n\xee\x91y\xf5|\xd0\xce_\x9e\xff\xed\xee\xfc\xfc\xe2\xe2)\x19V\xc1y\xc6c\xcd\xf2\xacvx\xfbr\x0c\xf2\xee\x83u\xc6\xdc\xbc\xd3c\x0c#-\xb8\xa7e-\x12/S\x8e\xb3\xd6\x1c\xca\xff\x80]\xad\xd0\xfd:9\xe7?\xe0\xb3Q\xf3\xe6c\xfe\x84\xef\xf6\xe6\x89\xe7\xe1\xbd\xe1\xf3\x1d\x0e\xcd\xa3\x9f\x02'O)m\x03\x02a\x96\x10\";%\xc9\xd3\xeax\xff\xb7\x17\xe0\xba\xf3\x1b\xc0O\x81\xfc\xdaj\x8d\x92[\x98a\xe5lX8\x94v\xa7F\xa2\xef\x892Q\xcc\xb4\xcf\x89\xa2\xa5J\x15\x8b\xa6<\xe3\xed\xe1\xae\xf8<\xce\x0d\xd7\xd9\xec+\xb7\x1aQ8\x90\xd9\xd9\xe8kH\xa1\xb3\xfad\xa3\xce\xae\xbc\xfc\xa4.O:\xb4\xf7\xf4\xb0\x9d\xdc\xcdFO3\xf5(#\xfd\xcd2\xb4\xf9\xf0\x10\x07\xb2\xd1\xcb\xe9\xf6r\x0f\xb3\x9f\xec\n\xec\xf3E\x99\xa0pBH\x89\x94\xf1\x1c\x9d\xb3.u\xb3\xf5\xdf\x8dp\x9d\xd1y\xe1p5\x83\xe1d\x9a>\xb0\x91\xa7\xe5\xc7h\x8aPNv\xa1\x1e\x11;\x14!MS\x92N+BM\x93=\x87\x8d=\xdb7G6\xc6\xa9\xdfmay\x8d\xf8R/\x94\xdeZ\x18kVQ\x93NY8\x17\xd6j\x14\x95v\xd7\x05\x96\x14uoZ7\xdd6\x9a\x07\xa4\x8c\xda\x83w\xd0\xc3\xa1\x1cfgj\xb7\x06]}\xdbC\x1f\xc5\xb9FWV\x07\x8a\xd7\xf1\xc2\x0fN\x8d\xa5\xffR\xfc.^\x80\xc3\xc8\x92b\xebv\xe5\x87\xe8\xe2\xd9\x1e&\xcf\xfa\xf4\xbbL\xfb9\\\xd2\xd5\x0f\xec\xb8\xf1\xd5\x7f\xe0E\xb9\x8ao3\xb2\xe5W\x8a\xf4w\xfee\xee\x8f\x00\x00\x00\xff\xffPK\x07\x08\xcd\xa79J\xb4\x05\x00\x00<\x19\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00 \x001/spec.ymlUT\x05\x00\x01\x80Cm8\xac\x92\xcdn\xea0\x10\x85\xf7y\x8a\x11\xb9\xd2]\x11`\x9b\xdd\xd5-\xa5R\xff6\xbc\xc0`\x8f\x93\x11\xc9\xd8\xb5\x9d\xaay\xfb*N\x00\xa1\x96\xd2J]\xc6\xfe|\xce\xe7\x89\xf3<\xcbsXK\xf4\xbd\xb3,\x11\xac\x01\x87j\x8f\x15Ap\xa4\xd8\xb0\xc2\xc8V\x8alDo((\xcf;\n\x10k\x02c\x1bM>\x00\x8a\x06\xc3MZ\xc5\x08-\xee :\x07x\xc8\x1aNC\xf6J>\xb0\x95\x12V\xc5\xb2X\xce\xb1q5\xae\xb2\xa1\xa6\xcc\xe6\xa0S\xb2\x8b\x89\xd8\xd6\x04-\xb2\x1ceZ\x146\x14b\xaa\xc9\x00b\xef\xa8<|(+\x91$>\x92f\xdc\xa6\x8d\x19:\xd7L\xea\x8b\xb7y\x8fm3\xcb\x00\x04\xdba\xf3\x10V\xf4\xe3\xb2\xa7\x97\x8e=\xe9\x12\xa2\xef\x86\xc0?\x9eL \xb3bq$\x07\xcb\x11\xff\xc4t\x92\xfc\x1b\xe0\xff\xdd\xbf\xa7\xcd\xfa\xe1y\xf3+\x9e\xaaF\xa9\xa8\xb1\xd5u\xd1\x13z\xd1\xf46\xfd\xac$\x81,,\x15h\x8c\x18(\x82&\xc3\xc2\x03\x15N\xca\x89>\xbaL\xe8\x97\x0e\x13\xb3\xf8\x89\x81U]K\x12\xd3\x00\xc0X\x9f\x9e\xd54\xcf\x8b.V\x85\x8f\"W\xbb\xeey\x87\x82\x80!P\x0c\xd0\x05\xd2\xb0\xeb\xbf\xd3\xb7O\x07\xcf\x1a\x0d6\xe1\xec\xee#s\xba\xfa{\x00\x00\x00\xff\xffPK\x07\x08\xea\xad\xacMG\x01\x00\x00Y\x03\x00\x00PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(\xeeO\xccS\xf8\x01\x00\x005\x05\x00\x00\x14\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x00\x00\x00\x001/changelog.spec.ymlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(ms,a\xbc\x00\x00\x00$\x01\x00\x00\x0f\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81C\x02\x00\x001/changelog.ymlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(W\xf9\xc8\xba\xbc\x01\x00\x00?\x04\x00\x00 \x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81E\x03\x00\x001/dataset/fields/fields.spec.ymlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(\xe8.L\x93\x92\x00\x00\x00\xb7\x00\x00\x00\x19\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81X\x05\x00\x001/dataset/fields/spec.ymlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(\xb9\xb2H\x06\xb5\x03\x00\x00\xc8\x10\x00\x00\x1b\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81:\x06\x00\x001/dataset/manifest.spec.ymlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(\xa7\xe6\xb9\xa6z\x01\x00\x00-\x05\x00\x00\x12\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81A\n\x00\x001/dataset/spec.ymlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(\xcc\x18\xa2\x06\xf4\x00\x00\x00\x1e\x05\x00\x00\x11\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x04\x0c\x00\x001/kibana/spec.ymlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(\xcd\xa79J\xb4\x05\x00\x00<\x19\x00\x00\x13\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81@\x0d\x00\x001/manifest.spec.ymlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(\xea\xad\xacMG\x01\x00\x00Y\x03\x00\x00\n\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81>\x13\x00\x001/spec.ymlUT\x05\x00\x01\x80Cm8PK\x05\x06\x00\x00\x00\x00 \x00 \x00\xa6\x02\x00\x00\xc6\x14\x00\x00\x00\x00" + data := "PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x00 \x001/changelog.spec.ymlUT\x05\x00\x01\x80Cm8\x9cT\xdfo\x94@\x10~\xe7\xaf\x98\x1c&\xd5(\xd0F\x8d\x91\xb7\xc6\xd6\x1as\xb6\x8d\xfab\xfc\x91,0\xc0\x94ew\xdd\x1dzw\xff\xbd\x81=\xee\xb8\x1f\xad\xd1y!\xf3\xcd\xb7\xc37\xdf2\x84a\x10\x86p\x81.\xb7\x94\xa1\x03\xae\x11\x9c\xc1\x9cJ\xca\x05\x93VPj;\xa0F\xe4\x8d\xa8\xf0\xc4\xc1\xbb\x0f\xe7\xd7W\x97\xf3\x9b+(Ib\x10\x86A\x7f\"\x0d\x00B\xb8\xbcG\xbb\xe2\x9aT\x05\x9d*\xd0B\x8d\x16\xa1\xd4R\xea\x85\x83\x8f_n\xae\xc1\xe55\xb6\x02\x9e\xd6\xcc\xc6\xa5Ir\xe7\xb4\x8a<\x18k[%\xcf^\xc0\xc2\x123*\x10\x0e\xbe\x9d\x7f\x9a\x0f\x1a,\x8aBd$\x89W\x01\x00\xaf\x0c\xa6 \xac\x15}F\x8c\xad\xeb\x05\x8c\x05\x9d\xdda\xce\x03 \x8a\x82\xfaA\x84\xbc\xb5\xda\xa0eB\x97B)\xa4\xc3\xa1n\xb6\xe8\x90\x03\xdc\xa3u\xa4\xd5\x98\x02\x14\x83=\xa6\xef\x92\xc2\xad\xf7ad\xc5\x1b\x96\x7f\xb3cK\xaa\xda\x80F0\xa3U)\x9c\xfc\xfa~\x1a\xbd\xfd\xf9\xfcG\xbc\xfb|r\xb2\xe1\xe2R\xb4Fnu\x00D0;\x8bO\xe3W\xb35\x92\xd7BUS\xc2\x8e\xb299\x06]\x8e, 5^\xdaCbG\xff|L\\\x9c\x92&^\xfa\xf8\x9b\xa3>\x0e}\xf51\x95\xbcS\xd8\x9b\xe6b\x9bl\x87\x8a\xf7N\x1c\xf5\xdc\xc7\xa1\x9b>\"\x98\xbd\xa7%dV7\xa8\x80\xb15R0\xce\x82\x83\xb6\x8f\x89\xfb\xba2\xf8\x7f\xaaT\xd7\x1eQ\x94Y\x14\x0d\xa9*\xf2\x0dgG\x18]U\xd2\xf2H\x01U-T\x8e-*>Rm\x94^\xa8\x88\x9c\xeb\xf6\x9aJR\xcd\xa3#\xceI5\xc0\x1a\x86\xb3\xa0-\xdc~^\x13\xb2~\xbb\xbd\xd0\xfe\x1b+\x90\x05\xc9\x7f\xf1\xe0\xe1\x9b\x19\xff \x15q\xddeq\xae\xdb\x04\xa5pLy\x92\xa1`\x97\x0cj\\r\xf6\xf2\xf5\xe9\x9b\xe9@\x16\x7fwd\xb1\x98\xf6\x8c\xa6\x03\xed\xe0\xbd\xb8\x1d\xa0w#8\xec\x13\x8d\x8b\xb3\xce\xd6\x9b\xf5'\x00\x00\xff\xffPK\x07\x08\xeeO\xccS\xf8\x01\x00\x005\x05\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00 \x001/changelog.ymlUT\x05\x00\x01\x80Cm8l\x8f\xb1N\x031\x10D{\x7f\xc5H\xae\xcfNZ\xf7\x14i\x80\"?\xb08{\xe7U\x1c\xdb\xca\xee!\xf1\xf7(\x864\x88v5\xfbf\x9e\xf7\xce{\x9c\x8b(V\xa9\x8cK\xcf\xfb\x8d\x9b)r\xa1\xb6\xb1B\x1a\xac0\x06\xe5+m\x0c\x1d\x9ce\x95L&\xbd\x05\x9c\x0c\xa2x};\x83\xfe\x8fLlp\xde\xbb\x05\x9f|W\xe9-\xe1\x18\x0e\xe1\xb0P\x1d\x85\x8e\x0e\xcf\xaa\xe4\x80\x05\x17\xd6|\x97a3xjbB\xf5\xf9\x89\xbe\xce1/\x95\xd4$\xe3\xfdO\xe3\xdc\xe4\x00\xc0\xbe\x06'p+\xd42?\x84\xe6\xb5J\xbb&\x14\xb3\xa1)\xc6M\xac\xec\x1f!\xf7[\xe4\x1f`\xfcUX\x1e\xc08\xf6Z5\x1e\xddw\x00\x00\x00\xff\xffPK\x07\x08ms,a\xbc\x00\x00\x00$\x01\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00 \x001/dataset/fields/fields.spec.ymlUT\x05\x00\x01\x80Cm8\x84T\xc1n\xd40\x10\xbd\xe7+\x9e\x1a$@\xea\xd2{nH\xe5\x82\xa0 \x95\x0b\xa7\xd5$\x9e$.^O\x18O\xba\xcd\xdf\xa38e\xb3\x8dV\xda[\xde\x9by\xe3g\x8f^\xca\xb2(K\xdcsj\xd4\xd7\x9c`=#\x0d\xdc\xf8\xd67d^\"ZQ\x10\x1c\x19%\xb6\xf7 \xcf\xa4^\xc6\x84\xd6spp\xdc\xfa\xe8\x97F\x1f8\x15eY\xcc\xfa\xaa\x00J|yf\x9d\xac\xf7\xb1\xc3\x18\x1d+zVF+!\xc81\xe1\xeb\xe3\x8f\x07\xa4\xa6\xe7\x03\xe1Co6\xa4\xea\xee\xee)I\xdc-\xe4'\xd1\xee\xee\xe3-\x8e\xea\xcd8\x82\x12~\x7f\xfe\xfe-;R&G\xb5\x0f\xde\xa6\x02\xb0i\xe0\nR?qc\x05@\xceeK\x14~\xaa\x0c\xac\xe69U0\x1d\xb9\x00\x86\x95*\x00 \xd2\x81\x97/\xc0\xe5w\x18fm\x85\x07:0\xa4].\xfa\xda\xb0\x1c\x94L}\xec2e\xde\xc2e\xf9\xaf\xb9r]\x9f\x89K\xfa{2\x9a\xabWG\x00\x1c\xc7\xc3\x7f\x0f;4\x12\x93Q\xb4\xfd\x1f\x9e\x8e\xa2\xeeT0~\xb1\x13\xd8\x16\x83\x9c\xc6\xed\xe0\xa3q\xc7z\xc2\xa9\x17]\xa5\xf5d|\x02N\xc6:\xac\xb0\x0dBkgO\xa1\xdd\xbf\xa5RC\x81\xdd\x86tt>\x91\x8c\xf7\x91\xa2\xa4\xf5D\x91\xc0\x14W\xec#\xe9\xb4\xb5\xbbW\x8a\xdd\xc6\xca\x86\x9bo\xb9\xa1\x96\x0bl\xc9\xd9\xc3[\xca\x0f\x1b\xa2S\x19\x87\x8c\xce\xf7vi\x95\x8f\xf3\xf3\x9dSWw\x9a\x8b\xe9\xf2\xb0\xb1\xde-\xe5[\x1c{\x8eY\x0c\x9f\xce\xfc\x00\xef\x94\xdb\n7\xe5MFe\x8e\xdak\xaa\x90\xa6h\xf4\x92S4\x88\x8f6\xa7\xd3$'_El\xf6\x96\xff\x02\xb9\xbb\x00\x94\xff\x8e^\xd9\xcdnv9.\xf9c>\xb6\xf8\x17\x00\x00\xff\xffPK\x07\x08W\xf9\xc8\xba\xbc\x01\x00\x00?\x04\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x19\x00 \x001/dataset/fields/spec.ymlUT\x05\x00\x01\x80Cm84\x8f1k\xc0 \x10\x85w\x7f\xc5C\n\x19\x8aI\xd7\xba\x16\xbau\xeb\xd6\x86r\xe8 \x07\xc6X5\xd0\xf4\xd7\x17m2\x89\x8f\xef\xbe{W3;\xab\x00\xf2^\x9a\xec\x89\xe2\xcb\x9e\x1a\xa7V-\x02\xc5\xca\npw\xa2\x00\x03\xcf\xd5\x15\xc9\x1d\xb6x\x15\x8e\xbe\xc2s\x904\xe6\x15\x00\xb43\xb3E\x90\xc8\xe3\x9b\xa95.\xc9b\xfa \xf3\xfbd\x9e\xd7\xeb\xfdZ\x1f\xef\xe4s>\xb78\x0d\xbc\xf0\xf7!\x85\xbdE+\xc7\xbf\xe1j\xf0\xc6^\xe8}\xc85\xe5\x1c\xc5Q\xdf\xb9\xfc\x98\x93\xb6\xa8\x07\xfaP8X\xe8y \xa3\xda\xdc\x0f\xecn\xad\xfe\x02\x00\x00\xff\xffPK\x07\x08t\xa7P\x0f\xa7\x00\x00\x00\xeb\x00\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1b\x00 \x001/dataset/manifest.spec.ymlUT\x05\x00\x01\x80Cm8\xccV_\x8f\xdb6\x0c\x7f\xcf\xa7 .\x0fk\x81%i\xb7\x87\x01y\x19\xba^\x81\xdd\xb0v\x052l\xd8\xd3A\xb1\xe9X\x85,y\"}w\xf9\xf6\x83$;\x91m9\xce\xed6\xa0|\xb2)\x8a\xe4\x8f\xe2\xbf\xe5r\xb1\\\xc2-Rf\xe5\x1e \xb8D\xa0\x1a3Y\xc8L\xb04\x1a\ncA@.X\x10\xf27\x04\x95\xd0\xb2@\xe2\xf5\xb1RPH\x85\x8b\xe5r\xe1\xael\x17\x00K\xf8\xf0\x80\xf6\xc8\xa5\xd4\x07ht\x8e\x16J\xb4\x08\x85Q\xca<\x12\xfc\xb2\xfb\xed\x13PVb%\xe0U\xc9\\\xd3v\xb3\xf9BF\xaf\x02sm\xeca\xf3\xfa[x\xb4\x92\x195\x08\x82\xbf\xde}\xfc\xd5;aQ\xe4b/\x95\xe4\xe3\x02\x80\x8f5n\xc1\xec\xbf`\xc6\x0b\x00\x91\xe7\xd2\xb9+\xd4gkj\xb4,\x91\xb6P\x08E\xb8\x00\xa8\xcf\xbc\x05\x00\x80\x16\x15\x86/\x80\xdcc\xaf\xdd\xe5-|\x12\x15\x82):\xb8\xadH\xb0El\xa5>x\x16KVi\x05\xbf\xbb\x93H\xc3zJ\x05\x00>\x89\xaaV\x9dK\x00+x\xf7\xe7\x0e\xf6R)\x17\xbc\n\xd9\xca\x8c\xfc\x99E\x85\x82\xd2\x06w\xdc\xc6\xe4J\xa3\xba\xa9\xce\x06\xf1\xa9F++\xd4,\xd4\x89\xb9G\x16\x93.\x9e\x0e\xbd\xeed\x04\x8e\xf55!\x1c\xba\x12\xe3u\xff\xca\x1ch\xd2\x8bX\x98\xd8\xa2\xa8h\"8\xfe\x0cLQ\xa0\xc5\x1c\xf6\xc7t\x88\x84\xb5\xe2\xd8r$\xe3Y\xdb(\xcf\x02]\xce\xb6@\xc3\x9ck\xb5\xeb\xba\xe1\x98\x91\x0cM\xa0!\xee@+\x10\x8f\xb4\xe9\x87\xab;\xa1\xef\x07\x0c_\x9fgF/o[\xd6s\xad\xbb$\xfd)\x91\xa4\x81\xe2\xf0\xbf\xcc\xce{\xa3\x14f\x0b.\x81\x0d|P\x82Xf\x84\xc2f%H\x9d\xe3\xd3I\x89o3!\x9f\xd67\xd7x\xff ,]0z\xe7\x1e\xdb I\xb1WH\xeb\x84\xca8\xf3\x02\x0d\xf2/\x16\x1eda\xa0kr1P:#\x03\xc5\x1d1\xa6\x1e\x9e?Z$^z\x9d\x90\x9e|\xe4@\xe9\xa7\x0e\xb4\x82\xd2\x10\xd3\xe8$\xee31\xf5\x1c\xbb\x15,\xbc\xa4k<]\xbc\xff\x8d\x83QK\x8ai\x05\x8cO\xc3\xc0\x87\x83\xa3\xa8\xd4\xb3\xa1&\xb5%\x8a3Pz\xc0\xbc\x04\xe6E\xe7~N\xbe\xc3da\x8f\x8faW\x1a\xcb1\xeb\x7f\xf5\xf7\xc6;\xecLH\xcdx\xb0am!\xb4\x0f2CW\xf2\x99\xd1\xdau\x1267#\x05U\xa3X\xce\x02z/\xf4\xc9\x7f\xa7\x8e\x85\xd4\xe1j\xad\x10\x1e\x84j\x90~\x9c\xc4\xb57F\xa1\xd0I#\x85h\x14\xa7\xcb\x15f\x91\xb3m\xc6\x97,\xfe\xddH\x8b\xf9,\xa8;:c\xea.}- \xa84\x8f\xf7\x0d\xa1\x9dE\xb1+M\xa3r\xe0RFp\xf6\xe85h\xf7\xfan\xa3u\x9a\xfc\xf0\x0f\xae\xbe\x08e\xd2\xdf9\x90\xe9\xd0t:\xe70\xde\x06\xb9\x90h\xaf\xe8\xb5\x9fS\x1d\xd8I,\xe3\xd1\x12(9`\xe2\x8b\x93ux\x19\xa5\xafE\xb7\xd3o7\x9b\xb7\xdf\xfd\xb0~\xb3~\xb3~;\xac\xb8\xa9\xec\\\xf9\x992b\xfa\x9e>\xa2H\x0c\xb5\x8bA~i\x08S;\xd2;\xd9\xfe\xeb\xa7\xdf}\xec\xe6*\xf4\xe7\xe8?\xb2\x12q\xfd\x82\xe7\xff1\xde4:E=\xd7\xfa\xbb\x88 B\xd75\x0b\xa9\xfd@\xefzpb\xf6\xcf\xcf\xfc\xd4\xac\xf7\xcb\xce}\xb7\xec\xc4!\x1bl-\xbd\x9d\xe8\xecPtab\x1f\x99\xf7\x0b.\xec!\x84\xccR\x1fF\xc9\xd5\xaf\xf7V\x08\x08\xb3n\xb4\xf4\xb7\xb8\xc1\xed\xc9\xd5\xa9\x12u=k\xeec+\xf4rsR\x1f\x90\xf8\xbe\x965*\xa9G\x83\xfeBb\x84\x9b\xd0\xdd<\xc5\xe9Z\xcb\xd7\xbe\x0b\xfc\x17;\xe2\xdd\xc0\xd9DY\xc3\xe5N3\xdb\"b\x81\xae,\xff \x00\x00\xff\xffPK\x07\x08\xb9\xb2H\x06\xb5\x03\x00\x00\xc8\x10\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x00 \x001/dataset/spec.ymlUT\x05\x00\x01\x80Cm8\xb4\x94O\x8f\xd3<\x10\xc6\xef\xfd\x14\xa3j\xa5\xbe\xafVi\xb9\x92\xdb\x8a?\x12\x88]\x0e\xcb\x05\xb1K5\xc4\x93b\xe48\xc63A\x14\xf1\xe1\x91\x9d\xa4I\xdbt\x93\x08q\xaa4y\x9e\xf1o\x1e\xd7\xc3\x8e\xb2t\x01\x80Ji\xd1\xa5E\xf3\xa2\xb4BV8\x85\x1c\x0d\xd3\x02 k+\x0b\x80\x04\x14q\xe6\xb5\x0b\xe2\x14^\x97F\x91\x8f\n\xd4V\xdb\x1d \xb0\xb6;C\xa0P\x90I@Q\xaem\xec\xbd\x00\x00\x90\xbd\xa3\x14\xf2\xe8\x8b\x05\x87\"\xe4m\n\xabO\x98\xfcz\x96<\x7fl~\xb7\x8f\xd7me\x15\x95\x9e\xbeW\xda\x93JA|E\xb1\xf4\x14\xf61\xf8\x19\xfaMK\xb8b(\xd0\xea\x9cX \xd7\xa6\xb6\x1e@\xbbB\xd3\xed\x96\x94\xc6\x0f\xf1\xe3\x12\x9d3:\xc3\xd0p\xf33\xd9ca\x96\x8d\xd8b\x11\x04m\xe3\xf5\xbe\xfb40\x06\xc0\x95\xa7<\x85\xe5zsp\x84\x9b\xe9l\xa3\xb9\xe7\x9a\x8c\xea\x85\xcd\xc7cty\xb7l\xd1\xc0\x93\x98j\xe9f&\x11\xee\xc8J\xe2\xc9\xa0\xd0,\xb2h<\x03\xeb\xaeu\xec\xdaO/~*+\xb0x\xc2b\x00u\x10\xb6\xc5\xad]\x87\xe2`\x94c\xc8\xa3\x80\xaf\x0c\xb2\xe8\x8c }\xf6\x15\x90\x99d4G\xea{\xfeUr\xc7`o\xec.<\xa3\xbbR\x118\xed\xc8hKs\xf3\xd4\xb1\xc7\xb6\xb5OLp\x08\xfe\x0c\xff%\xe5X\x19i\x8e\x18\"<8\x07\x16\x00\x1cm\xab\xcf\xaan\xf6\xb0\xfeo_\x98\xdf\xdf\xb8\xb4\xff_\xadz\xd2\x0b\x7f\x84\x13\xa4\xfb\xca\xb9\xd2K\x88\xf22\x15\x83\xb6\xf0\xf1\xe6\xf6\xddt\xbc\xf5\xf5Cx\xab}\xa0Y\x0b\x0c.>\xbe\xbf\x18\xe1\xed\xfd\xfb\xbby#\x84Xg\xcc\x10\xe4c\x13\x9c\xd2c\xe1\x0c\x01\xfd\x08\x1b\xe0\xa9\xfd\xdf\xact\x8e\xfam\xd4\xaf\xfb\xe7\xcd@\x9b\x80u\xfe\xd2\x848f\xdcn\xd4\x80\xc6\x80V\x01W_\x92\xfa)\x8d\xee\x84e\xe8r\x01\xe3O\x00\x00\x00\xff\xffPK\x07\x08P\xc1\xcd\xd5\xeb\x01\x00\x00\x0c\x08\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00 \x001/kibana/spec.ymlUT\x05\x00\x01\x80Cm8\xcc\x90\xbdN\xc30\x10\xc7w\x9e\xe2\x94\xa5\x03\xa2\xec\xde\x10\x12\x0bbcDB\xd7\xdc\x85\x1er\xce\xc6\xe7V\xc0\xd3\xa3\x98$\x94\xb6CP\x84\x94\xd1\xe7\xff\x97~\x00\x16\xb9v\x17\x00\x00H$Y\x82\xa2\xbf\x0d\x9aY\xb39h\xd0\x1b\x97\xdfz\xb8\x95\xd7\x15\x10[\x9d$v\x06\x07w\xc1\x13\xa7\xa2AQ\xd1\x17\xb8\x97\x0d*\x02\xa1m7\x01\x13\x01\x9aq\xb6b\x06\xc8\x1f\x91\x1d4\xc5\xd5\x9f\x14[v?\xfa\xfe\x9a\xf8m'\x89\xe9p\xc9\xf1\x96\x9357\xc7\xb5\xd0\x88\x1f\xbcc\xf9\xe1\xa9\x0f|`\x12|,\xdf\x15\xc6\xe8\xa5\xc6.\xf1\xfa\xd5\x82V\xa38b\xce\x9c\xd4\xc1j}\xf9\xb4\xee\xfeV\x7fb\xb2\x17\xdb\xa1\x97\xcf\x92=\x91\xcb/\xcf<6g\xea\x97\xc5\xc7p\xcf\x04\xc6\x98\xea\xedD<\xdf\xe2y\\Nk\x97\x85\xa5\xc58\x91F\x8bq\x1e\x8a\xb1jY\x04D\x89\xdf\x87\x94\x89,\xaabz\xeeM\xd5,.zn\xc1\xff#\xfa\n\x00\x00\xff\xffPK\x07\x08\xed\xdd\xda\xfb\xff\x00\x00\x00\xa4\x05\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x13\x00 \x001/manifest.spec.ymlUT\x05\x00\x01\x80Cm8\xccXmo[\xbb\x0d\xfe\xee_A\xd8\x05\x92,\xb3\x9d\xb4\x18\x86\x18\xd8\x82\xa0-\xd6niW,\xfd\xb2\xdb\xf6\x1a\xb2L\x1f\xab\xd1\x91NE\x1e;\xce\xaf\xbf8\xef:o\x8e\x91\xa4\xb8\xd5'\x8b\xa2\xc5\x87\xd4C\x8a:\xa3\xd1`4\x827H\xd2\xa9\x05\x12\xf0\x1a\x81\"\x94j\xa5\xa4`e\x0d\xac\xacK\xa5\x91\x90\xb7\"\xc0#\x82P(\x03\xa10j\x85\xc4\x93]\xa8a\xa54\x0eF\xa3A\xf2\xcf\xd9\x00`\x04o7\xe8v\xbcV&\x80\xd8,\xd1\xc1\x1a\x1d\xc2\xcajm\xb7\x04\xff\xbe\xf9\xefG \xb9\xc6P\xc0\xf1\x9a9\xa2\xd9t\xfa\x9d\xac\x19g\xc2\x89u\xc1\xf4\xe4\xaf\xb0u\x8a\x19\x0d\x08\x82\xff_}\xb8N\xb18\x14K\xb1PZ\xf1n\x00\xc0\xbb\x08g`\x17\xdfQ\xf2\x00@,\x97*A-\xf4'g#t\xac\x90f\xb0\x12\x9ap\x00\x10U\xb2\x01\x00$\xdb\x85\x82\xe7\x1bt\xa4\xac\xc9d\x00\xcb4\x18Q\xb2\xcd\x0c>\xaf\x11\xf2u\xb0+?\x10\xed0\x85\x82!&\\\xc2b\x07\xbcVThN\xf2\x8d3\xac\xc4N\x99 \x17E\x82\x19\x9d\x99\xc1\xd1\xef\xc7_\xce\xc6\x17\xdfNO\xbeN\xda\xbf\x8e/g\xe3\xf4\xf7\xd5\xf871\xbe\x1f\x7f;=\xbe\x9c}\x9d\xd4$'\x7f99\xb9L\xc4\xa7u\xf1\xe5\x8b\xa3\xdc\x18\xde\x890\xd2\x85\xf3\x00c\x18\x9eO\xce&g\xc3tnD\x88\xbd!H\x16\x1b\xfe\x1f\xe4\xd5\x171\xbe?\x1b_\xcc\xbf\x9d\xf6\x83\x10\x91\x90kL\xa7\xacX\xf7\x83HW\x0fG\xd1\xb6tUY\xf27\xef\xb2w\x05\xda\x9a\x00\x9d/}\xbaixo\x18\x03\x972&]z\x1c\xf5\x0e\n\xfd\x9fC\xa8\xb3\xc9yA(\xad$\x1a\xea?\xce|=\xaf\x0f\xdb\xb5\x92\xebZ~)\x82\x05&\x05\xc4\xa1FA\xb8\xdc\x17p\x13\x87\x15\x8a\x85 %K\xb3+\x11k\x9e\xd5\x84m\xe0\xd5j\xba{/\x05wQ\xca\xc0\x87\x0f\xa2\x8eH5\xce\xbd\x0bBS'w\xbb\x17\x0bq^\x06\x0fgG\x1d\x14\xdeE\xe8T\x88\x86\x85\xae\x02\x81,\xcaI z\xd1\xb6\xfe,\x05c`\x9d\xaa\x94j\x88_\x97\xcb\xc0\xb6<\xed\xaaH\xc2\x02\x93\x8c\xa3:z\xe1\x9c\xd8\xe5\x12\xc5\x18\x96{w\xbaWw0\xad-[\xf2g\xf7\xb1Co.\xb5\x8d\x97\xfe\xdc\x9a\x95\n\xe6\xa10\"\xc0\xc4\xb5\xfa\x1a\x0be\xd0\xf9\x1bJ\x17\xfa\xb3\x98\xd8\xfa\x82\xa5`Alk6Q\x0bb%\xe7\xc4B\xdez\xf2\xc0\xda@\xe3\xbc \xe96^\xa03\xc8\xe8\x9b\xd5\xc2\x04\xb1\x08j\xb2\x10\x89D\x80\xf3\x1f1\xc6\xbe\xbd\xd0\x1a\xc5\xb6\x16\xa41\x18\xe4\xadu\xbeyc\xb9\xbc\xcb<\xb1\xa59\xed\x88\xd1\xf7*rv\x19KV\x9b\xec\x06.\xc4\x842v\x0dQ\x1cE\xd6\xf9Qd%o\x91\xeb`\xf2\x1a7O\"\xec\xac\xf6V\xb6\xb8\xa8N\xb6\xc1@\x7f]Z\x93]\xfb=\xd4\xb3\x86\xd8 e\x98\x1a\xc5\xc6\xa3\x9f\x14\x06\x16\x08\xca\x10\x0b\xad\x9b\xc5\xa6l0\x92\xb1\xa7\xc9\xc8\x14r\xbdf\xbb\x91\x8c[\xb5\x10FT\xf3\x06\xd4\xff\xa4\xcbEH\x08\xa4\x0d#\xc1j\xa1\x11\xb6\x8a\xd7\x9dmE\x0f\xca\x07\x90zZ]8\xa1}9\x15\xa33\xf1\xb2\xd1>\xa4l\x8ca\xf8\xcf\x7f\xfc}rQ\\\x0dJ\xf6\x9d\xd5\xb5\"N\xeaY\xaa\x91\xf6{{\x9b\xa9\x07\xebC#$\x87\x04\xa4;\x1c\xe4d\xdd\xab\x1a\xec\xff\xa1\x16\xac6I\x0dNN\xc9\xa6\xf58\xf1\xe1\x88@\x85 \xbf\x92\x16yR\xdb\xa07\x8e\xddQ\x1c\xc3p\xaa\xc2`\xaam`\xe7Y\xcf4\xa1M0\xf4Y\xe0\xb7O\xd9\xa8\xdf\x1aE\x03\x95 {*\x98\xbc\xa3\xb9\xb6\x81\xf51\x90\xba\xdf\x07\xe1F\xdd\x97-\xdcs\xa0x\xf5\xf2\xee\xd5\xcba3\x13\xfa\xed\x7fx\xff\xe1my\x8b\x17 \x9e\xf1\x88\xd2\x9d\xa6\xb4 N\xefB]\xe1r\xf8#V\x0e\x97~\xf5\"\x975\x1c$\x1d\xa2\xa1\xb5\xe5\xfd)\xe1\xe9%\xd3\xbcT\x08\"d\x02\xe9P\xf0CO\x8f_:[\x12\xf7L\xea\xde\xf3\xe7L\x96.\xf3\xe4\xa5\xb9\x9c\x13\xba\x0d\xba\xe4\x02\xe6\x98&\x91y\\\nU\xa7\xf1T\x84y\"\xbd\xfb\xfc\xf9\xd3\x1b\xb8I\xc1\xc1M\n\xee\x91y\xf5|\xd0\xce_\x9e\xff\xed\xee\xfc\xfc\xe2\xe2)\x19V\xc1y\xc6c\xcd\xf2\xacvx\xfbr\x0c\xf2\xee\x83u\xc6\xdc\xbc\xd3c\x0c#-\xb8\xa7e-\x12/S\x8e\xb3\xd6\x1c\xca\xff\x80]\xad\xd0\xfd:9\xe7?\xe0\xb3Q\xf3\xe6c\xfe\x84\xef\xf6\xe6\x89\xe7\xe1\xbd\xe1\xf3\x1d\x0e\xcd\xa3\x9f\x02'O)m\x03\x02a\x96\x10\";%\xc9\xd3\xeax\xff\xb7\x17\xe0\xba\xf3\x1b\xc0O\x81\xfc\xdaj\x8d\x92[\x98a\xe5lX8\x94v\xa7F\xa2\xef\x892Q\xcc\xb4\xcf\x89\xa2\xa5J\x15\x8b\xa6<\xe3\xed\xe1\xae\xf8<\xce\x0d\xd7\xd9\xec+\xb7\x1aQ8\x90\xd9\xd9\xe8kH\xa1\xb3\xfad\xa3\xce\xae\xbc\xfc\xa4.O:\xb4\xf7\xf4\xb0\x9d\xdc\xcdFO3\xf5(#\xfd\xcd2\xb4\xf9\xf0\x10\x07\xb2\xd1\xcb\xe9\xf6r\x0f\xb3\x9f\xec\n\xec\xf3E\x99\xa0pBH\x89\x94\xf1\x1c\x9d\xb3.u\xb3\xf5\xdf\x8dp\x9d\xd1y\xe1p5\x83\xe1d\x9a>\xb0\x91\xa7\xe5\xc7h\x8aPNv\xa1\x1e\x11;\x14!MS\x92N+BM\x93=\x87\x8d=\xdb7G6\xc6\xa9\xdfmay\x8d\xf8R/\x94\xdeZ\x18kVQ\x93NY8\x17\xd6j\x14\x95v\xd7\x05\x96\x14uoZ7\xdd6\x9a\x07\xa4\x8c\xda\x83w\xd0\xc3\xa1\x1cfgj\xb7\x06]}\xdbC\x1f\xc5\xb9FWV\x07\x8a\xd7\xf1\xc2\x0fN\x8d\xa5\xffR\xfc.^\x80\xc3\xc8\x92b\xebv\xe5\x87\xe8\xe2\xd9\x1e&\xcf\xfa\xf4\xbbL\xfb9\\\xd2\xd5\x0f\xec\xb8\xf1\xd5\x7f\xe0E\xb9\x8ao3\xb2\xe5W\x8a\xf4w\xfee\xee\x8f\x00\x00\x00\xff\xffPK\x07\x08\xcd\xa79J\xb4\x05\x00\x00<\x19\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00 \x001/spec.ymlUT\x05\x00\x01\x80Cm8\xac\x92\xcfn\xdb0\x0c\x87\xef~\x8a\x1f\x92\x01;\xc5i\xaf\xbe\x0d]\xd7\x01\xfbw\xe9\x0b0\x16\x95\x10\xb1)M\x94\x87\xf9\xed\x07\xabvR\x0cA\xb2\x01=Z\xfcH~$\xbd^W\xeb5\x1e5\xa71\x06\xd1\x8c\xe0\x11\xa9=\xd2\x9ea\x91[\xf1\xd2R\x96\xa0u\xf5\x82~dk\x93\xec\xd8\x90\x0f\x0c\x1f:\xc7\xc9@\xea\xe0\xa5+\xaf\x94\xd1\xd3\x911D\xd0Rk\xcaF\xf5\x8b\x93I\xd0\x06\xf7\xf5]}\xb7\xa1.\x1e\xe8\xbe\x9a\xda4\x15@\xce\xc9\xd4\x89\xba\x87\xa0\x995[\x83\x9c\x06\xae\x80vy\xa8\x80\x0d\\Q\x88\xb9\x94z>0z\x12=Y\xf7\xa4\xe2\xd9r\xf1\xa9\x00 \x8f\x91\x9b\xf3\xe7\\\xec\x1b;\xa1\xe7\x12ZQ\x8c\xdd<\xe7\xf6\xf7f\xa4\xbe[\x15T\xa9\x9f\xc2K\xc9z\\\x02\x89\x7f\x0e\x92\xd8\x9d\x0c\x81w\x89}\x83U\xbd=\xd1\xd3`K\xca\x05\xebY\xf8\xbd\xe1\xe1\xf3\x87\xefO\x8f_\x7f<\xbd\xa1s{ \xdds\x17\xf6\x97\xa4=u\xf6\x97\xf5\x99\xbf\xa2\xfd\xa9\x9c\xbb\xd8\x90\xa8\xe8\x1e\x8e2\x19g8\xf6\xa2\xe5|\xf6\xda\xbf\xf0\xaf\xb4f\xfc\xe6\x0egn\xfb\x7f.\xa1\x1dz\xd6\\v\x02\x1fR\xf9E\xe75_\xb5\n\xad]V\xba\xd9\xf3\x8b\xecH d\xc6\xd90\x18;\xec\xc6\x7f\xed{,\xc9\xb7o\xf3\xc2\x9d\x97\xf1'\x00\x00\xff\xffPK\x07\x08\xcf\x08b\xadY\x01\x00\x00\xb5\x03\x00\x00PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(\xeeO\xccS\xf8\x01\x00\x005\x05\x00\x00\x14\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x00\x00\x00\x001/changelog.spec.ymlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(ms,a\xbc\x00\x00\x00$\x01\x00\x00\x0f\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81C\x02\x00\x001/changelog.ymlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(W\xf9\xc8\xba\xbc\x01\x00\x00?\x04\x00\x00 \x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81E\x03\x00\x001/dataset/fields/fields.spec.ymlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(t\xa7P\x0f\xa7\x00\x00\x00\xeb\x00\x00\x00\x19\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81X\x05\x00\x001/dataset/fields/spec.ymlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(\xb9\xb2H\x06\xb5\x03\x00\x00\xc8\x10\x00\x00\x1b\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81O\x06\x00\x001/dataset/manifest.spec.ymlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(P\xc1\xcd\xd5\xeb\x01\x00\x00\x0c\x08\x00\x00\x12\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81V\n\x00\x001/dataset/spec.ymlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(\xed\xdd\xda\xfb\xff\x00\x00\x00\xa4\x05\x00\x00\x11\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x8a\x0c\x00\x001/kibana/spec.ymlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(\xcd\xa79J\xb4\x05\x00\x00<\x19\x00\x00\x13\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xd1\x0d\x00\x001/manifest.spec.ymlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(\xcf\x08b\xadY\x01\x00\x00\xb5\x03\x00\x00\n\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xcf\x13\x00\x001/spec.ymlUT\x05\x00\x01\x80Cm8PK\x05\x06\x00\x00\x00\x00 \x00 \x00\xa6\x02\x00\x00i\x15\x00\x00\x00\x00" fs.Register(data) } \ No newline at end of file diff --git a/code/go/internal/spec_test.go b/code/go/internal/spec_test.go index 0dfbba61b..c681b00e6 100644 --- a/code/go/internal/spec_test.go +++ b/code/go/internal/spec_test.go @@ -3,9 +3,10 @@ package internal import ( "testing" - _ "github.com/elastic/package-spec/code/go/internal/spec" "github.com/rakyll/statik/fs" "github.com/stretchr/testify/require" + + _ "github.com/elastic/package-spec/code/go/internal/spec" ) func TestBundledSpecs(t *testing.T) { diff --git a/code/go/internal/validator/errors.go b/code/go/internal/validator/errors.go index 29286e3d0..780e024e6 100644 --- a/code/go/internal/validator/errors.go +++ b/code/go/internal/validator/errors.go @@ -19,8 +19,8 @@ func (ve ValidationErrors) Error() string { errorWord = "error" } fmt.Fprintf(&message, "found %v validation %v:\n", len(ve), errorWord) - for _, err := range ve { - fmt.Fprintf(&message, "\t%v\n", err) + for idx, err := range ve { + fmt.Fprintf(&message, "%4d. %v\n", idx+1, err) } return message.String() diff --git a/code/go/internal/validator/folder.go b/code/go/internal/validator/folder.go new file mode 100644 index 000000000..4b1e379e2 --- /dev/null +++ b/code/go/internal/validator/folder.go @@ -0,0 +1,217 @@ +package validator + +import ( + "fmt" + "io/ioutil" + "net/http" + "os" + "path" + "path/filepath" + "regexp" + + "github.com/pkg/errors" + "gopkg.in/yaml.v3" +) + +const itemTypeFile = "file" +const itemTypeFolder = "folder" + +type folderSpec struct { + fs http.FileSystem + specPath string + commonSpec +} + +type folderItemSpec struct { + Description string `yaml:"description"` + ItemType string `yaml:"type"` + ContentMediaType string `yaml:"contentMediaType"` + Name string `yaml:"name"` + Pattern string `yaml:"pattern"` + Required bool `yaml:"required"` + Ref string `yaml:"$ref"` + commonSpec `yaml:",inline"` +} + +type commonSpec struct { + AdditionalContents bool `yaml:"additionalContents"` + Contents []folderItemSpec `yaml:"contents"` +} + +func newFolderSpec(fs http.FileSystem, specPath string) (*folderSpec, error) { + specFile, err := fs.Open(specPath) + if err != nil { + return nil, errors.Wrap(err, "could not open folder specification file") + } + defer specFile.Close() + + data, err := ioutil.ReadAll(specFile) + if err != nil { + return nil, errors.Wrap(err, "could not read folder specification file") + } + + var wrapper struct { + Spec commonSpec `yaml:"spec"` + } + if err := yaml.Unmarshal(data, &wrapper); err != nil { + return nil, errors.Wrap(err, "could not parse folder specification file") + } + + spec := folderSpec{ + fs: fs, + specPath: specPath, + commonSpec: wrapper.Spec, + } + + return &spec, nil +} + +func (s *folderSpec) validate(folderPath string) ValidationErrors { + var errs ValidationErrors + files, err := ioutil.ReadDir(folderPath) + if err != nil { + errs = append(errs, errors.Wrapf(err, "could not read folder [%s]", folderPath)) + return errs + } + + for _, file := range files { + fileName := file.Name() + itemSpec, err := s.findItemSpec(fileName) + if err != nil { + errs = append(errs, err) + continue + } + + if itemSpec == nil && s.AdditionalContents { + // No spec found for current folder item but we do allow additional contents in folder. + continue + } + + if itemSpec == nil && !s.AdditionalContents { + // No spec found for current folder item and we do not allow additional contents in folder. + errs = append(errs, fmt.Errorf("item [%s] is not allowed in folder [%s]", fileName, folderPath)) + continue + } + + if file.IsDir() { + if !itemSpec.isSameType(file) { + errs = append(errs, fmt.Errorf("[%s] is a folder but is expected to be a file", fileName)) + continue + } + + if itemSpec.Ref == "" && itemSpec.Contents == nil { + // No recursive validation needed + continue + } + + var subFolderSpec *folderSpec + if itemSpec.Ref != "" { + subFolderSpecPath := path.Join(filepath.Dir(s.specPath), itemSpec.Ref) + subFolderSpec, err = newFolderSpec(s.fs, subFolderSpecPath) + if err != nil { + errs = append(errs, err) + continue + } + } else if itemSpec.Contents != nil { + subFolderSpec = &folderSpec{ + fs: s.fs, + specPath: s.specPath, + commonSpec: commonSpec{ + AdditionalContents: itemSpec.AdditionalContents, + Contents: itemSpec.Contents, + }, + } + } + + subFolderPath := path.Join(folderPath, fileName) + subErrs := subFolderSpec.validate(subFolderPath) + if len(subErrs) > 0 { + errs = append(errs, subErrs...) + } + + } else { + if !itemSpec.isSameType(file) { + errs = append(errs, fmt.Errorf("[%s] is a file but is expected to be a folder", fileName)) + continue + } + // TODO: more validation for file item + } + } + + // validate that required items in spec are all accounted for + for _, itemSpec := range s.Contents { + if !itemSpec.Required { + continue + } + + fileFound, err := itemSpec.matchingFileExists(files) + if err != nil { + errs = append(errs, err) + continue + } + + if !fileFound { + var err error + if itemSpec.Name != "" { + err = fmt.Errorf("expecting to find [%s] %s in folder [%s]", itemSpec.Name, itemSpec.ItemType, folderPath) + } else if itemSpec.Pattern != "" { + err = fmt.Errorf("expecting to find %s matching pattern [%s] in folder [%s]", itemSpec.ItemType, itemSpec.Pattern, folderPath) + } + errs = append(errs, err) + } + } + return errs +} + +func (s *folderSpec) findItemSpec(folderItemName string) (*folderItemSpec, error) { + for _, itemSpec := range s.Contents { + if itemSpec.Name != "" && itemSpec.Name == folderItemName { + return &itemSpec, nil + } + if itemSpec.Pattern != "" { + isMatch, err := regexp.MatchString(itemSpec.Pattern, folderItemName) + if err != nil { + return nil, errors.Wrap(err, "invalid folder item spec pattern") + } + if isMatch { + return &itemSpec, nil + } + } + } + + // No item spec found + return nil, nil +} + +func (s *folderItemSpec) matchingFileExists(files []os.FileInfo) (bool, error) { + if s.Name != "" { + for _, file := range files { + if file.Name() == s.Name { + return s.isSameType(file), nil + } + } + } else if s.Pattern != "" { + for _, file := range files { + isMatch, err := regexp.MatchString(s.Pattern, file.Name()) + if err != nil { + return false, errors.Wrap(err, "invalid folder item spec pattern") + } + if isMatch { + return s.isSameType(file), nil + } + } + } + + return false, nil +} + +func (s *folderItemSpec) isSameType(file os.FileInfo) bool { + switch s.ItemType { + case itemTypeFile: + return !file.IsDir() + case itemTypeFolder: + return file.IsDir() + } + + return false +} diff --git a/code/go/internal/validator/package.go b/code/go/internal/validator/package.go new file mode 100644 index 000000000..42fd3e81f --- /dev/null +++ b/code/go/internal/validator/package.go @@ -0,0 +1,61 @@ +package validator + +import ( + "fmt" + "io/ioutil" + "os" + "path" + + "github.com/Masterminds/semver/v3" + "github.com/pkg/errors" + "gopkg.in/yaml.v3" +) + +// Package represents an Elastic Package Registry package +type Package struct { + SpecVersion *semver.Version + RootPath string +} + +// NewPackage creates a new Package from a path to the package's root folder +func NewPackage(pkgRootPath string) (*Package, error) { + info, err := os.Stat(pkgRootPath) + if os.IsNotExist(err) { + return nil, errors.Wrapf(err, "no package found at path [%v]", pkgRootPath) + } + + if !info.IsDir() { + return nil, fmt.Errorf("no package folder found at path [%v]", pkgRootPath) + } + + pkgManifestPath := path.Join(pkgRootPath, "manifest.yml") + info, err = os.Stat(pkgManifestPath) + if os.IsNotExist(err) { + return nil, errors.Wrapf(err, "no package manifest file found at path [%v]", pkgManifestPath) + } + + data, err := ioutil.ReadFile(pkgManifestPath) + if err != nil { + return nil, fmt.Errorf("could not read package manifest file [%v]", pkgManifestPath) + } + + var manifest struct { + SpecVersion string `yaml:"format_version"` + } + if err := yaml.Unmarshal(data, &manifest); err != nil { + return nil, errors.Wrapf(err, "could not parse package manifest file [%v]", pkgManifestPath) + } + + specVersion, err := semver.NewVersion(manifest.SpecVersion) + if err != nil { + return nil, errors.Wrapf(err, "could not read specification version from package manifest file [%v]", pkgManifestPath) + } + + // Instantiate Package object and return it + p := Package{ + specVersion, + pkgRootPath, + } + + return &p, nil +} diff --git a/code/go/internal/validator/package_test.go b/code/go/internal/validator/package_test.go new file mode 100644 index 000000000..7a0b0abb4 --- /dev/null +++ b/code/go/internal/validator/package_test.go @@ -0,0 +1,43 @@ +package validator + +import ( + "path" + "testing" + + "github.com/Masterminds/semver/v3" + "github.com/stretchr/testify/require" +) + +func TestNewPackage(t *testing.T) { + tests := map[string]struct { + expectedErrContains string + expectedSpecVersion *semver.Version + }{ + "good": { + expectedSpecVersion: semver.MustParse("1.0.4"), + }, + "non_existent": { + expectedErrContains: "no package found at", + }, + "no_manifest": { + expectedErrContains: "no package manifest file found at", + }, + "no_spec_version": { + expectedErrContains: "could not read specification version", + }, + } + + for pkgName, test := range tests { + pkgRootPath := path.Join("test", "packages", pkgName) + pkg, err := NewPackage(pkgRootPath) + if test.expectedErrContains == "" { + require.NoError(t, err) + require.Equal(t, test.expectedSpecVersion, pkg.SpecVersion) + require.Equal(t, pkgRootPath, pkg.RootPath) + } else { + require.Error(t, err) + require.Contains(t, err.Error(), test.expectedErrContains) + require.Nil(t, pkg) + } + } +} diff --git a/code/go/internal/validator/spec.go b/code/go/internal/validator/spec.go new file mode 100644 index 000000000..ffb22bc9d --- /dev/null +++ b/code/go/internal/validator/spec.go @@ -0,0 +1,58 @@ +package validator + +import ( + "net/http" + "path" + "strconv" + + "github.com/Masterminds/semver/v3" + "github.com/pkg/errors" + "github.com/rakyll/statik/fs" + + // Loads package specs as an in-memory filesystem + _ "github.com/elastic/package-spec/code/go/internal/spec" +) + +// Spec represents a package specification +type Spec struct { + version semver.Version + fs http.FileSystem + specPath string +} + +// NewSpec creates a new Spec for the given version +func NewSpec(version semver.Version) (*Spec, error) { + majorVersion := strconv.FormatUint(version.Major(), 10) + + bundle, err := fs.New() + if err != nil { + return nil, errors.Wrap(err, "could not load specifications") + } + + specPath := "/" + majorVersion + if _, err := bundle.Open(specPath); err != nil { + return nil, errors.Wrapf(err, "could not load specification for version [%s]", version.String()) + } + + s := Spec{ + version, + bundle, + specPath, + } + + return &s, nil +} + +// ValidatePackage validates the given Package against the Spec +func (s Spec) ValidatePackage(pkg Package) ValidationErrors { + var errs ValidationErrors + + rootSpecPath := path.Join(s.specPath, "spec.yml") + rootSpec, err := newFolderSpec(s.fs, rootSpecPath) + if err != nil { + errs = append(errs, errors.Wrap(err, "could not read root folder spec file")) + return errs + } + + return rootSpec.validate(pkg.RootPath) +} diff --git a/code/go/internal/validator/spec_test.go b/code/go/internal/validator/spec_test.go new file mode 100644 index 000000000..6906b15a7 --- /dev/null +++ b/code/go/internal/validator/spec_test.go @@ -0,0 +1,31 @@ +package validator + +import ( + "testing" + + "github.com/Masterminds/semver/v3" + "github.com/stretchr/testify/require" +) + +func TestNewSpec(t *testing.T) { + tests := map[string]struct { + expectedErrContains string + }{ + "1.0.0": {}, + "9999.99.999": { + "could not load specification for version [9999.99.999]", + }, + } + + for version, test := range tests { + spec, err := NewSpec(*semver.MustParse(version)) + if test.expectedErrContains == "" { + require.NoError(t, err) + require.IsType(t, &Spec{}, spec) + } else { + require.Error(t, err) + require.Contains(t, err.Error(), test.expectedErrContains) + require.Nil(t, spec) + } + } +} diff --git a/code/go/internal/validator/test/packages/good/changelog.yml b/code/go/internal/validator/test/packages/good/changelog.yml new file mode 100644 index 000000000..e69de29bb diff --git a/code/go/internal/validator/test/packages/good/dataset/foo/fields/some_fields.yml b/code/go/internal/validator/test/packages/good/dataset/foo/fields/some_fields.yml new file mode 100644 index 000000000..e69de29bb diff --git a/code/go/internal/validator/test/packages/good/dataset/foo/manifest.yml b/code/go/internal/validator/test/packages/good/dataset/foo/manifest.yml new file mode 100644 index 000000000..e69de29bb diff --git a/code/go/internal/validator/test/packages/good/docs/.empty b/code/go/internal/validator/test/packages/good/docs/.empty new file mode 100644 index 000000000..e69de29bb diff --git a/code/go/internal/validator/test/packages/good/manifest.yml b/code/go/internal/validator/test/packages/good/manifest.yml new file mode 100644 index 000000000..24ed53d91 --- /dev/null +++ b/code/go/internal/validator/test/packages/good/manifest.yml @@ -0,0 +1 @@ +format_version: 1.0.4 \ No newline at end of file diff --git a/code/go/internal/validator/test/packages/no_manifest/.keep b/code/go/internal/validator/test/packages/no_manifest/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/code/go/internal/validator/test/packages/no_spec_version/manifest.yml b/code/go/internal/validator/test/packages/no_spec_version/manifest.yml new file mode 100644 index 000000000..b20212f0e --- /dev/null +++ b/code/go/internal/validator/test/packages/no_spec_version/manifest.yml @@ -0,0 +1,2 @@ +# no format_version in this file +name: mypackage \ No newline at end of file diff --git a/code/go/pkg/validator/errors.go b/code/go/pkg/validator/errors.go new file mode 100644 index 000000000..20fbf0d75 --- /dev/null +++ b/code/go/pkg/validator/errors.go @@ -0,0 +1,8 @@ +package validator + +import ( + "github.com/elastic/package-spec/code/go/internal/validator" +) + +// ValidationErrors is an Error that contains a iterable collection of validation error messages. +type ValidationErrors validator.ValidationErrors diff --git a/code/go/pkg/validator/validator.go b/code/go/pkg/validator/validator.go index 00e09ab87..0ac70fd71 100644 --- a/code/go/pkg/validator/validator.go +++ b/code/go/pkg/validator/validator.go @@ -1,13 +1,31 @@ package validator import ( + "errors" + "github.com/elastic/package-spec/code/go/internal/validator" ) // ValidateFromPath validates a package located at the given path against the // appropriate specification and returns any errors. func ValidateFromPath(packageRootPath string) error { - // TODO: Noop for now. Implement actual validation. - var errs validator.ValidationErrors - return errs + pkg, err := validator.NewPackage(packageRootPath) + if err != nil { + return err + } + + if pkg.SpecVersion == nil { + return errors.New("could not determine specification version for package") + } + + spec, err := validator.NewSpec(*pkg.SpecVersion) + if err != nil { + return err + } + + if errs := spec.ValidatePackage(*pkg); errs != nil && len(errs) > 0 { + return errs + } + + return nil } diff --git a/code/go/pkg/validator/validator_test.go b/code/go/pkg/validator/validator_test.go new file mode 100644 index 000000000..88f73f765 --- /dev/null +++ b/code/go/pkg/validator/validator_test.go @@ -0,0 +1,13 @@ +package validator + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestValidate(t *testing.T) { + pkgRootPath := "../../internal/validator/test/packages/good" + errs := ValidateFromPath(pkgRootPath) + require.NoError(t, errs) +} diff --git a/versions/1/dataset/fields/spec.yml b/versions/1/dataset/fields/spec.yml index 580180efa..601f3adb8 100644 --- a/versions/1/dataset/fields/spec.yml +++ b/versions/1/dataset/fields/spec.yml @@ -1,7 +1,9 @@ spec: -- description: Fields definition - type: file - pattern: '[a-z0-9][a-z0-9_]+[a-z0-9]\.yml' - required: true - contentMediaType: "application/x-yaml" - $ref: "./fields.spec.yml" + additionalContents: false + contents: + - description: Fields definition + type: file + pattern: '[a-z0-9][a-z0-9_]+[a-z0-9]\.yml' + required: true + contentMediaType: "application/x-yaml" + $ref: "./fields.spec.yml" diff --git a/versions/1/dataset/spec.yml b/versions/1/dataset/spec.yml index b4131f567..64c4059ae 100644 --- a/versions/1/dataset/spec.yml +++ b/versions/1/dataset/spec.yml @@ -1,45 +1,64 @@ spec: -- description: Folder containing a single dataset definition - type: folder - pattern: '[a-z0-9][a-z0-9_]+[a-z0-9]' - minOccurences: 1 + additionalContents: false contents: - - description: A dataset's manifest file - type: file - contentMediaType: "application/x-yaml" - name: "manifest.yml" - required: true - $ref: "./manifest.spec.yml" - - description: Folder containing field definitions - type: folder - name: fields - required: true - $ref: "./fields/spec.yml" - - description: Folder containing agent-related definitions + - description: Folder containing a single dataset definition type: folder - name: agent + pattern: '[a-z0-9][a-z0-9_]+[a-z0-9]' required: true + additionalContents: false contents: - - description: Folder containing agent stream definitions + - description: A dataset's manifest file + type: file + contentMediaType: "application/x-yaml" + name: "manifest.yml" + required: true + $ref: "./manifest.spec.yml" + - description: Folder containing field definitions type: folder - name: stream + name: fields required: true + $ref: "./fields/spec.yml" + - description: Folder containing agent-related definitions + type: folder + name: agent + required: false + additionalContents: false contents: - - description: Agent stream definition - type: file - name: "stream.yml.hbs" - contentMediaType: "application/x-hbs" + - description: Folder containing agent stream definitions + type: folder + name: stream required: true - - description: Folder containing Elasticsearch assets - type: folder - name: elasticsearch - contents: - - description: Folder containing Elasticsearch Ingest Node pipeline definitions + additionalContents: false + - description: Folder containing Elasticsearch assets type: folder - name: ingest_pipeline + name: elasticsearch + additionalContents: false contents: - - description: Default ingest pipeline definition - type: file - name: "default.yml" - contentMediaType: "application/x-yaml" - required: true + - description: Folder containing Elasticsearch Ingest Node pipeline definitions + type: folder + name: ingest_pipeline + additionalContents: false + contents: + - description: Default ingest pipeline definition + type: file + pattern: '^default\.(yml|json)$' + required: true + - description: Supporting ingest pipeline definitions in YAML + type: file + pattern: '.+\.yml' + contentMediaType: "application/x-yaml" + required: false + - description: Supporting ingest pipeline definitions in JSON + type: file + pattern: '.+\.json' + contentMediaType: "application/json" + required: false + - description: Sample event file + type: file + name: "sample_event.json" + contentMediaType: "application/json" + required: false + - description: Folder containing testing related files and sub-folders + type: folder + name: "test" + required: false \ No newline at end of file diff --git a/versions/1/kibana/spec.yml b/versions/1/kibana/spec.yml index 525dcab60..00f329fad 100644 --- a/versions/1/kibana/spec.yml +++ b/versions/1/kibana/spec.yml @@ -1,46 +1,48 @@ spec: - - description: Folder containing Kibana dashboard assets - type: folder - name: dashboard - required: false + additionalContents: false contents: - - description: A dashboard asset file - type: file - contentMediaType: "application/json" - pattern: '.+\.json' - - description: Folder containing Kibana visualization assets - type: folder - name: visualization - required: false - contents: - - description: A visualization asset file - type: file - contentMediaType: "application/json" - pattern: '.+\.json' - - description: Folder containing Kibana saved search assets - type: folder - name: search - required: false - contents: - - description: A saved search asset file - type: file - contentMediaType: "application/json" - pattern: '.+\.json' - - description: Folder containing Kibana map assets - type: folder - name: map - required: false - contents: - - description: A map asset file - type: file - contentMediaType: "application/json" - pattern: '.+\.json' - - description: Folder containing Kibana index pattern assets - type: folder - name: "index_pattern" - required: false - contents: - - description: An index pattern asset file - type: file - contentMediaType: "application/json" - pattern: '.+\.json' + - description: Folder containing Kibana dashboard assets + type: folder + name: dashboard + required: false + contents: + - description: A dashboard asset file + type: file + contentMediaType: "application/json" + pattern: '.+\.json' + - description: Folder containing Kibana visualization assets + type: folder + name: visualization + required: false + contents: + - description: A visualization asset file + type: file + contentMediaType: "application/json" + pattern: '.+\.json' + - description: Folder containing Kibana saved search assets + type: folder + name: search + required: false + contents: + - description: A saved search asset file + type: file + contentMediaType: "application/json" + pattern: '.+\.json' + - description: Folder containing Kibana map assets + type: folder + name: map + required: false + contents: + - description: A map asset file + type: file + contentMediaType: "application/json" + pattern: '.+\.json' + - description: Folder containing Kibana index pattern assets + type: folder + name: "index_pattern" + required: false + contents: + - description: An index pattern asset file + type: file + contentMediaType: "application/json" + pattern: '.+\.json' diff --git a/versions/1/spec.yml b/versions/1/spec.yml index 63a29acf4..651513fb4 100644 --- a/versions/1/spec.yml +++ b/versions/1/spec.yml @@ -5,29 +5,31 @@ ## version: 1.0.0-alpha1 spec: -- description: The main package manifest file - type: file - contentMediaType: "application/x-yaml" - name: "manifest.yml" - required: true - $ref: "./manifest.spec.yml" -- description: The package's CHANGELOG file - type: file - contentMediaType: "application/x-yaml" - name: "changelog.yml" - required: true - $ref: "./changelog.spec.yml" -- description: Folder containing dataset definitions - type: folder - name: dataset - required: true - $ref: "./dataset/spec.yml" -- description: Folder containing documentation for the package - type: folder - name: docs - required: true -- description: Folder containing Kibana assets used by the package - type: folder - name: kibana - required: false - $ref: "./kibana/spec.yml" \ No newline at end of file + additionalContents: true + contents: + - description: The main package manifest file + type: file + contentMediaType: "application/x-yaml" + name: "manifest.yml" + required: true + $ref: "./manifest.spec.yml" + - description: The package's CHANGELOG file + type: file + contentMediaType: "application/x-yaml" + name: "changelog.yml" + required: false + $ref: "./changelog.spec.yml" + - description: Folder containing dataset definitions + type: folder + name: dataset + required: true + $ref: "./dataset/spec.yml" + - description: Folder containing documentation for the package + type: folder + name: docs + required: true + - description: Folder containing Kibana assets used by the package + type: folder + name: kibana + required: false + $ref: "./kibana/spec.yml" \ No newline at end of file