diff options
43 files changed, 706 insertions, 611 deletions
diff --git a/client/js/app/yarn.lock b/client/js/app/yarn.lock index e3d408e242e..984bdbd2f48 100644 --- a/client/js/app/yarn.lock +++ b/client/js/app/yarn.lock @@ -599,115 +599,115 @@ resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz#d0fce5d07b0620caa282b5131c297bb60f9d87e6" integrity sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww== -"@esbuild/android-arm64@0.19.7": - version "0.19.7" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.19.7.tgz#646156aea43e8e6723de6e94a4ac07c5aed41be1" - integrity sha512-YEDcw5IT7hW3sFKZBkCAQaOCJQLONVcD4bOyTXMZz5fr66pTHnAet46XAtbXAkJRfIn2YVhdC6R9g4xa27jQ1w== - -"@esbuild/android-arm@0.19.7": - version "0.19.7" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.19.7.tgz#0827b49aed813c33ea18ee257c1728cdc4a01030" - integrity sha512-YGSPnndkcLo4PmVl2tKatEn+0mlVMr3yEpOOT0BeMria87PhvoJb5dg5f5Ft9fbCVgtAz4pWMzZVgSEGpDAlww== - -"@esbuild/android-x64@0.19.7": - version "0.19.7" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.19.7.tgz#fa294ed5214d88219d519e0ab1bbb0253a89b864" - integrity sha512-jhINx8DEjz68cChFvM72YzrqfwJuFbfvSxZAk4bebpngGfNNRm+zRl4rtT9oAX6N9b6gBcFaJHFew5Blf6CvUw== - -"@esbuild/darwin-arm64@0.19.7": - version "0.19.7" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.19.7.tgz#e24d2ed545749ff251eabe8bce11fefa688892d3" - integrity sha512-dr81gbmWN//3ZnBIm6YNCl4p3pjnabg1/ZVOgz2fJoUO1a3mq9WQ/1iuEluMs7mCL+Zwv7AY5e3g1hjXqQZ9Iw== - -"@esbuild/darwin-x64@0.19.7": - version "0.19.7" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.19.7.tgz#02d1f8a572874c90d8f55dde8a859e5145bd06f6" - integrity sha512-Lc0q5HouGlzQEwLkgEKnWcSazqr9l9OdV2HhVasWJzLKeOt0PLhHaUHuzb8s/UIya38DJDoUm74GToZ6Wc7NGQ== - -"@esbuild/freebsd-arm64@0.19.7": - version "0.19.7" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.7.tgz#bc6a69b9a7915da278f0a5ebaec069c813982c22" - integrity sha512-+y2YsUr0CxDFF7GWiegWjGtTUF6gac2zFasfFkRJPkMAuMy9O7+2EH550VlqVdpEEchWMynkdhC9ZjtnMiHImQ== - -"@esbuild/freebsd-x64@0.19.7": - version "0.19.7" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.19.7.tgz#ec3708488625d70e565968ceea1355e7c8613865" - integrity sha512-CdXOxIbIzPJmJhrpmJTLx+o35NoiKBIgOvmvT+jeSadYiWJn0vFKsl+0bSG/5lwjNHoIDEyMYc/GAPR9jxusTA== - -"@esbuild/linux-arm64@0.19.7": - version "0.19.7" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.19.7.tgz#8e04b66c306858f92d4f90f8222775270755e88a" - integrity sha512-inHqdOVCkUhHNvuQPT1oCB7cWz9qQ/Cz46xmVe0b7UXcuIJU3166aqSunsqkgSGMtUCWOZw3+KMwI6otINuC9g== - -"@esbuild/linux-arm@0.19.7": - version "0.19.7" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.19.7.tgz#12d5b65e089029ee1fe4c591b60969c9b1a85355" - integrity sha512-Y+SCmWxsJOdQtjcBxoacn/pGW9HDZpwsoof0ttL+2vGcHokFlfqV666JpfLCSP2xLxFpF1lj7T3Ox3sr95YXww== - -"@esbuild/linux-ia32@0.19.7": - version "0.19.7" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.19.7.tgz#01eabc2a3ad9039e115db650268e4f48f910dbe2" - integrity sha512-2BbiL7nLS5ZO96bxTQkdO0euGZIUQEUXMTrqLxKUmk/Y5pmrWU84f+CMJpM8+EHaBPfFSPnomEaQiG/+Gmh61g== - -"@esbuild/linux-loong64@0.19.7": - version "0.19.7" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.19.7.tgz#70681113632970e6a5766607bbdb98aa18cf4d5f" - integrity sha512-BVFQla72KXv3yyTFCQXF7MORvpTo4uTA8FVFgmwVrqbB/4DsBFWilUm1i2Oq6zN36DOZKSVUTb16jbjedhfSHw== - -"@esbuild/linux-mips64el@0.19.7": - version "0.19.7" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.19.7.tgz#f63c022a71a3d70c482d1943a27cb8997021e230" - integrity sha512-DzAYckIaK+pS31Q/rGpvUKu7M+5/t+jI+cdleDgUwbU7KdG2eC3SUbZHlo6Q4P1CfVKZ1lUERRFP8+q0ob9i2w== - -"@esbuild/linux-ppc64@0.19.7": - version "0.19.7" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.19.7.tgz#614eafd08b0c50212f287b948b3c08d6e60f221f" - integrity sha512-JQ1p0SmUteNdUaaiRtyS59GkkfTW0Edo+e0O2sihnY4FoZLz5glpWUQEKMSzMhA430ctkylkS7+vn8ziuhUugQ== - -"@esbuild/linux-riscv64@0.19.7": - version "0.19.7" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.19.7.tgz#31d3b63f92f65968268a8e61ba59872538e80e88" - integrity sha512-xGwVJ7eGhkprY/nB7L7MXysHduqjpzUl40+XoYDGC4UPLbnG+gsyS1wQPJ9lFPcxYAaDXbdRXd1ACs9AE9lxuw== - -"@esbuild/linux-s390x@0.19.7": - version "0.19.7" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.19.7.tgz#be94974e0caa0783ae05f9477fd7170b9ac29cb0" - integrity sha512-U8Rhki5PVU0L0nvk+E8FjkV8r4Lh4hVEb9duR6Zl21eIEYEwXz8RScj4LZWA2i3V70V4UHVgiqMpszXvG0Yqhg== - -"@esbuild/linux-x64@0.19.7": - version "0.19.7" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.19.7.tgz#84e8018a913dd4ecee954623e395984aef3d0007" - integrity sha512-ZYZopyLhm4mcoZXjFt25itRlocKlcazDVkB4AhioiL9hOWhDldU9n38g62fhOI4Pth6vp+Mrd5rFKxD0/S+7aQ== - -"@esbuild/netbsd-x64@0.19.7": - version "0.19.7" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.19.7.tgz#98898ba8800374c9df9bb182ca4f69fcecaf4411" - integrity sha512-/yfjlsYmT1O3cum3J6cmGG16Fd5tqKMcg5D+sBYLaOQExheAJhqr8xOAEIuLo8JYkevmjM5zFD9rVs3VBcsjtQ== - -"@esbuild/openbsd-x64@0.19.7": - version "0.19.7" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.19.7.tgz#46dc4eda2adb51f16361b1ad10e9b3f4938c4573" - integrity sha512-MYDFyV0EW1cTP46IgUJ38OnEY5TaXxjoDmwiTXPjezahQgZd+j3T55Ht8/Q9YXBM0+T9HJygrSRGV5QNF/YVDQ== - -"@esbuild/sunos-x64@0.19.7": - version "0.19.7" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.19.7.tgz#1650d40dd88412ecc11490119cd23cbaf661a591" - integrity sha512-JcPvgzf2NN/y6X3UUSqP6jSS06V0DZAV/8q0PjsZyGSXsIGcG110XsdmuWiHM+pno7/mJF6fjH5/vhUz/vA9fw== - -"@esbuild/win32-arm64@0.19.7": - version "0.19.7" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.19.7.tgz#e61de6c4eb204d83fd912f3ae6812cc8c7d32d25" - integrity sha512-ZA0KSYti5w5toax5FpmfcAgu3ZNJxYSRm0AW/Dao5up0YV1hDVof1NvwLomjEN+3/GMtaWDI+CIyJOMTRSTdMw== - -"@esbuild/win32-ia32@0.19.7": - version "0.19.7" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.19.7.tgz#3d9c159d42c67e37a433e44ef8217c661cb6f6d0" - integrity sha512-CTOnijBKc5Jpk6/W9hQMMvJnsSYRYgveN6O75DTACCY18RA2nqka8dTZR+x/JqXCRiKk84+5+bRKXUSbbwsS0A== - -"@esbuild/win32-x64@0.19.7": - version "0.19.7" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.19.7.tgz#02c4446f802706098d8e6ee70cf2b7aba96ded0b" - integrity sha512-gRaP2sk6hc98N734luX4VpF318l3w+ofrtTu9j5L8EQXF+FzQKV6alCOHMVoJJHvVK/mGbwBXfOL1HETQu9IGQ== +"@esbuild/android-arm64@0.19.8": + version "0.19.8" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.19.8.tgz#fb7130103835b6d43ea499c3f30cfb2b2ed58456" + integrity sha512-B8JbS61bEunhfx8kasogFENgQfr/dIp+ggYXwTqdbMAgGDhRa3AaPpQMuQU0rNxDLECj6FhDzk1cF9WHMVwrtA== + +"@esbuild/android-arm@0.19.8": + version "0.19.8" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.19.8.tgz#b46e4d9e984e6d6db6c4224d72c86b7757e35bcb" + integrity sha512-31E2lxlGM1KEfivQl8Yf5aYU/mflz9g06H6S15ITUFQueMFtFjESRMoDSkvMo8thYvLBax+VKTPlpnx+sPicOA== + +"@esbuild/android-x64@0.19.8": + version "0.19.8" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.19.8.tgz#a13db9441b5a4f4e4fec4a6f8ffacfea07888db7" + integrity sha512-rdqqYfRIn4jWOp+lzQttYMa2Xar3OK9Yt2fhOhzFXqg0rVWEfSclJvZq5fZslnz6ypHvVf3CT7qyf0A5pM682A== + +"@esbuild/darwin-arm64@0.19.8": + version "0.19.8" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.19.8.tgz#49f5718d36541f40dd62bfdf84da9c65168a0fc2" + integrity sha512-RQw9DemMbIq35Bprbboyf8SmOr4UXsRVxJ97LgB55VKKeJOOdvsIPy0nFyF2l8U+h4PtBx/1kRf0BelOYCiQcw== + +"@esbuild/darwin-x64@0.19.8": + version "0.19.8" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.19.8.tgz#75c5c88371eea4bfc1f9ecfd0e75104c74a481ac" + integrity sha512-3sur80OT9YdeZwIVgERAysAbwncom7b4bCI2XKLjMfPymTud7e/oY4y+ci1XVp5TfQp/bppn7xLw1n/oSQY3/Q== + +"@esbuild/freebsd-arm64@0.19.8": + version "0.19.8" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.8.tgz#9d7259fea4fd2b5f7437b52b542816e89d7c8575" + integrity sha512-WAnPJSDattvS/XtPCTj1tPoTxERjcTpH6HsMr6ujTT+X6rylVe8ggxk8pVxzf5U1wh5sPODpawNicF5ta/9Tmw== + +"@esbuild/freebsd-x64@0.19.8": + version "0.19.8" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.19.8.tgz#abac03e1c4c7c75ee8add6d76ec592f46dbb39e3" + integrity sha512-ICvZyOplIjmmhjd6mxi+zxSdpPTKFfyPPQMQTK/w+8eNK6WV01AjIztJALDtwNNfFhfZLux0tZLC+U9nSyA5Zg== + +"@esbuild/linux-arm64@0.19.8": + version "0.19.8" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.19.8.tgz#c577932cf4feeaa43cb9cec27b89cbe0df7d9098" + integrity sha512-z1zMZivxDLHWnyGOctT9JP70h0beY54xDDDJt4VpTX+iwA77IFsE1vCXWmprajJGa+ZYSqkSbRQ4eyLCpCmiCQ== + +"@esbuild/linux-arm@0.19.8": + version "0.19.8" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.19.8.tgz#d6014d8b98b5cbc96b95dad3d14d75bb364fdc0f" + integrity sha512-H4vmI5PYqSvosPaTJuEppU9oz1dq2A7Mr2vyg5TF9Ga+3+MGgBdGzcyBP7qK9MrwFQZlvNyJrvz6GuCaj3OukQ== + +"@esbuild/linux-ia32@0.19.8": + version "0.19.8" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.19.8.tgz#2379a0554307d19ac4a6cdc15b08f0ea28e7a40d" + integrity sha512-1a8suQiFJmZz1khm/rDglOc8lavtzEMRo0v6WhPgxkrjcU0LkHj+TwBrALwoz/OtMExvsqbbMI0ChyelKabSvQ== + +"@esbuild/linux-loong64@0.19.8": + version "0.19.8" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.19.8.tgz#e2a5bbffe15748b49356a6cd7b2d5bf60c5a7123" + integrity sha512-fHZWS2JJxnXt1uYJsDv9+b60WCc2RlvVAy1F76qOLtXRO+H4mjt3Tr6MJ5l7Q78X8KgCFudnTuiQRBhULUyBKQ== + +"@esbuild/linux-mips64el@0.19.8": + version "0.19.8" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.19.8.tgz#1359331e6f6214f26f4b08db9b9df661c57cfa24" + integrity sha512-Wy/z0EL5qZYLX66dVnEg9riiwls5IYnziwuju2oUiuxVc+/edvqXa04qNtbrs0Ukatg5HEzqT94Zs7J207dN5Q== + +"@esbuild/linux-ppc64@0.19.8": + version "0.19.8" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.19.8.tgz#9ba436addc1646dc89dae48c62d3e951ffe70951" + integrity sha512-ETaW6245wK23YIEufhMQ3HSeHO7NgsLx8gygBVldRHKhOlD1oNeNy/P67mIh1zPn2Hr2HLieQrt6tWrVwuqrxg== + +"@esbuild/linux-riscv64@0.19.8": + version "0.19.8" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.19.8.tgz#fbcf0c3a0b20f40b5fc31c3b7695f0769f9de66b" + integrity sha512-T2DRQk55SgoleTP+DtPlMrxi/5r9AeFgkhkZ/B0ap99zmxtxdOixOMI570VjdRCs9pE4Wdkz7JYrsPvsl7eESg== + +"@esbuild/linux-s390x@0.19.8": + version "0.19.8" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.19.8.tgz#989e8a05f7792d139d5564ffa7ff898ac6f20a4a" + integrity sha512-NPxbdmmo3Bk7mbNeHmcCd7R7fptJaczPYBaELk6NcXxy7HLNyWwCyDJ/Xx+/YcNH7Im5dHdx9gZ5xIwyliQCbg== + +"@esbuild/linux-x64@0.19.8": + version "0.19.8" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.19.8.tgz#b187295393a59323397fe5ff51e769ec4e72212b" + integrity sha512-lytMAVOM3b1gPypL2TRmZ5rnXl7+6IIk8uB3eLsV1JwcizuolblXRrc5ShPrO9ls/b+RTp+E6gbsuLWHWi2zGg== + +"@esbuild/netbsd-x64@0.19.8": + version "0.19.8" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.19.8.tgz#c1ec0e24ea82313cb1c7bae176bd5acd5bde7137" + integrity sha512-hvWVo2VsXz/8NVt1UhLzxwAfo5sioj92uo0bCfLibB0xlOmimU/DeAEsQILlBQvkhrGjamP0/el5HU76HAitGw== + +"@esbuild/openbsd-x64@0.19.8": + version "0.19.8" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.19.8.tgz#0c5b696ac66c6d70cf9ee17073a581a28af9e18d" + integrity sha512-/7Y7u77rdvmGTxR83PgaSvSBJCC2L3Kb1M/+dmSIvRvQPXXCuC97QAwMugBNG0yGcbEGfFBH7ojPzAOxfGNkwQ== + +"@esbuild/sunos-x64@0.19.8": + version "0.19.8" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.19.8.tgz#2a697e1f77926ff09fcc457d8f29916d6cd48fb1" + integrity sha512-9Lc4s7Oi98GqFA4HzA/W2JHIYfnXbUYgekUP/Sm4BG9sfLjyv6GKKHKKVs83SMicBF2JwAX6A1PuOLMqpD001w== + +"@esbuild/win32-arm64@0.19.8": + version "0.19.8" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.19.8.tgz#ec029e62a2fca8c071842ecb1bc5c2dd20b066f1" + integrity sha512-rq6WzBGjSzihI9deW3fC2Gqiak68+b7qo5/3kmB6Gvbh/NYPA0sJhrnp7wgV4bNwjqM+R2AApXGxMO7ZoGhIJg== + +"@esbuild/win32-ia32@0.19.8": + version "0.19.8" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.19.8.tgz#cbb9a3146bde64dc15543e48afe418c7a3214851" + integrity sha512-AIAbverbg5jMvJznYiGhrd3sumfwWs8572mIJL5NQjJa06P8KfCPWZQ0NwZbPQnbQi9OWSZhFVSUWjjIrn4hSw== + +"@esbuild/win32-x64@0.19.8": + version "0.19.8" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.19.8.tgz#c8285183dbdb17008578dbacb6e22748709b4822" + integrity sha512-bfZ0cQ1uZs2PqpulNL5j/3w+GDhP36k1K5c38QdQg+Swy51jFZWWeIkteNsufkQxp986wnqRRsb/bHbY1WQ7TA== "@eslint-community/eslint-utils@^4.2.0": version "4.4.0" @@ -777,31 +777,31 @@ resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.1.4.tgz#19654d1026cc410975d46445180e70a5089b3e7d" integrity sha512-qprfWkn82Iw821mcKofJ5Pk9wgioHicxcQMxx+5zt5GSKoqdWvgG5AxVmpmUUjzTLPVSH5auBrhI93Deayn/DA== -"@fortawesome/fontawesome-common-types@6.4.2": - version "6.4.2" - resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.4.2.tgz#1766039cad33f8ad87f9467b98e0d18fbc8f01c5" - integrity sha512-1DgP7f+XQIJbLFCTX1V2QnxVmpLdKdzzo2k8EmvDOePfchaIGQ9eCHj2up3/jNEbZuBqel5OxiaOJf37TWauRA== +"@fortawesome/fontawesome-common-types@6.5.0": + version "6.5.0" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.5.0.tgz#5d3912d28a2fb3e6c867320eb27a71f23e7bcb29" + integrity sha512-vYC8oN2l8meu05sRi1j3Iie/HNFAeIxpitYFhsUrBc11TxiMken9QdXnSQ0q16FYsOSt/6soxs5ghdk+VYGiog== "@fortawesome/fontawesome-svg-core@^6": - version "6.4.2" - resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.4.2.tgz#37f4507d5ec645c8b50df6db14eced32a6f9be09" - integrity sha512-gjYDSKv3TrM2sLTOKBc5rH9ckje8Wrwgx1CxAPbN5N3Fm4prfi7NsJVWd1jklp7i5uSCVwhZS5qlhMXqLrpAIg== + version "6.5.0" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.5.0.tgz#4957e163bb890963442c110c5290703af21803d9" + integrity sha512-5DrR+oxQr+ruRQ3CEVV8DSCT/q8Atm56+FzAs0P6eW/epW47OmecSpSwc/YTlJ3u5BfPKUBSGyPR2qjZ+5eIgA== dependencies: - "@fortawesome/fontawesome-common-types" "6.4.2" + "@fortawesome/fontawesome-common-types" "6.5.0" "@fortawesome/free-regular-svg-icons@^6": - version "6.4.2" - resolved "https://registry.yarnpkg.com/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.4.2.tgz#aee79ed76ce5dd04931352f9d83700761b8b1b25" - integrity sha512-0+sIUWnkgTVVXVAPQmW4vxb9ZTHv0WstOa3rBx9iPxrrrDH6bNLsDYuwXF9b6fGm+iR7DKQvQshUH/FJm3ed9Q== + version "6.5.0" + resolved "https://registry.yarnpkg.com/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.5.0.tgz#c2c448695efc0b2a16d126ff8e3cb94e1544778b" + integrity sha512-RaBW/y0jKcCyEPM+NYuBs3bQXuLYZHnXABQPmg6qwuRxNb2EUmyCcVUECUH2dkFmMjggh/xvl6n6y62Pl19JkA== dependencies: - "@fortawesome/fontawesome-common-types" "6.4.2" + "@fortawesome/fontawesome-common-types" "6.5.0" "@fortawesome/free-solid-svg-icons@^6": - version "6.4.2" - resolved "https://registry.yarnpkg.com/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.4.2.tgz#33a02c4cb6aa28abea7bc082a9626b7922099df4" - integrity sha512-sYwXurXUEQS32fZz9hVCUUv/xu49PEJEyUOsA51l6PU/qVgfbTb2glsTEaJngVVT8VqBATRIdh7XVgV1JF1LkA== + version "6.5.0" + resolved "https://registry.yarnpkg.com/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.5.0.tgz#bc50a291948fa43b1a9502548ac0b02e7b1f2433" + integrity sha512-6ZPq8mme67Q7O9Fbp2O+Z7mPZbcWTsRv555JLftLaTodiV0Wq+99YgMhyQ8O6mgNQfComqS9OEvqs7M8ySA92g== dependencies: - "@fortawesome/fontawesome-common-types" "6.4.2" + "@fortawesome/fontawesome-common-types" "6.5.0" "@fortawesome/react-fontawesome@^0": version "0.2.0" @@ -1274,65 +1274,65 @@ resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.13.0.tgz#7e29c4ee85176d9c08cb0f4456bff74d092c5065" integrity sha512-5dMOnVnefRsl4uRnAdoWjtVTdh8e6aZqgM4puy9nmEADH72ck+uXwzpJLEKE9Q6F8ZljNewLgmTfkxUrBdv4WA== -"@rollup/rollup-android-arm-eabi@4.5.0": - version "4.5.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.5.0.tgz#5984f98288150a2c34928de023bbd122d61ce754" - integrity sha512-OINaBGY+Wc++U0rdr7BLuFClxcoWaVW3vQYqmQq6B3bqQ/2olkaoz+K8+af/Mmka/C2yN5j+L9scBkv4BtKsDA== - -"@rollup/rollup-android-arm64@4.5.0": - version "4.5.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.5.0.tgz#8456a8c623cca4042ae4bf2ce03d875a02433191" - integrity sha512-UdMf1pOQc4ZmUA/NTmKhgJTBimbSKnhPS2zJqucqFyBRFPnPDtwA8MzrGNTjDeQbIAWfpJVAlxejw+/lQyBK/w== - -"@rollup/rollup-darwin-arm64@4.5.0": - version "4.5.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.5.0.tgz#76be6832eee21dabc28f84f9f54fbfcc66615992" - integrity sha512-L0/CA5p/idVKI+c9PcAPGorH6CwXn6+J0Ys7Gg1axCbTPgI8MeMlhA6fLM9fK+ssFhqogMHFC8HDvZuetOii7w== - -"@rollup/rollup-darwin-x64@4.5.0": - version "4.5.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.5.0.tgz#66bd162a3fea48cb1cef50cedccfbeee5685b444" - integrity sha512-QZCbVqU26mNlLn8zi/XDDquNmvcr4ON5FYAHQQsyhrHx8q+sQi/6xduoznYXwk/KmKIXG5dLfR0CvY+NAWpFYQ== - -"@rollup/rollup-linux-arm-gnueabihf@4.5.0": - version "4.5.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.5.0.tgz#a0e6b2a1d67a4ba0c2a61985175f65c05abc5f73" - integrity sha512-VpSQ+xm93AeV33QbYslgf44wc5eJGYfYitlQzAi3OObu9iwrGXEnmu5S3ilkqE3Pr/FkgOiJKV/2p0ewf4Hrtg== - -"@rollup/rollup-linux-arm64-gnu@4.5.0": - version "4.5.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.5.0.tgz#5434b844a47ba4e35602ee312de9f39b38b1777b" - integrity sha512-OrEyIfpxSsMal44JpEVx9AEcGpdBQG1ZuWISAanaQTSMeStBW+oHWwOkoqR54bw3x8heP8gBOyoJiGg+fLY8qQ== - -"@rollup/rollup-linux-arm64-musl@4.5.0": - version "4.5.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.5.0.tgz#149cab95107821fe4ae46d5f2c0658c5b0e56b9c" - integrity sha512-1H7wBbQuE6igQdxMSTjtFfD+DGAudcYWhp106z/9zBA8OQhsJRnemO4XGavdzHpGhRtRxbgmUGdO3YQgrWf2RA== - -"@rollup/rollup-linux-x64-gnu@4.5.0": - version "4.5.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.5.0.tgz#6929bf3013e9d599605953ea1bc51f35376bfff7" - integrity sha512-FVyFI13tXw5aE65sZdBpNjPVIi4Q5mARnL/39UIkxvSgRAIqCo5sCpCELk0JtXHGee2owZz5aNLbWNfBHzr71Q== - -"@rollup/rollup-linux-x64-musl@4.5.0": - version "4.5.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.5.0.tgz#a17f5decabf05b74aad684de56cf43a72a289a0b" - integrity sha512-eBPYl2sLpH/o8qbSz6vPwWlDyThnQjJfcDOGFbNjmjb44XKC1F5dQfakOsADRVrXCNzM6ZsSIPDG5dc6HHLNFg== - -"@rollup/rollup-win32-arm64-msvc@4.5.0": - version "4.5.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.5.0.tgz#f145f10c33aa187a11fd60933465be46667e6e42" - integrity sha512-xaOHIfLOZypoQ5U2I6rEaugS4IYtTgP030xzvrBf5js7p9WI9wik07iHmsKaej8Z83ZDxN5GyypfoyKV5O5TJA== - -"@rollup/rollup-win32-ia32-msvc@4.5.0": - version "4.5.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.5.0.tgz#798614b191f9ce1dc58079d1dfbc234c71df9e0e" - integrity sha512-Al6quztQUrHwcOoU2TuFblUQ5L+/AmPBXFR6dUvyo4nRj2yQRK0WIUaGMF/uwKulvRcXkpHe3k9A8Vf93VDktA== - -"@rollup/rollup-win32-x64-msvc@4.5.0": - version "4.5.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.5.0.tgz#748970e066839e33ed8c935061e370c4ab050517" - integrity sha512-8kdW+brNhI/NzJ4fxDufuJUjepzINqJKLGHuxyAtpPG9bMbn8P5mtaCcbOm0EzLJ+atg+kF9dwg8jpclkVqx5w== +"@rollup/rollup-android-arm-eabi@4.6.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.6.0.tgz#c08a454d70605aacad17530a953791ea385e37d5" + integrity sha512-keHkkWAe7OtdALGoutLY3utvthkGF+Y17ws9LYT8pxMBYXaCoH/8dXS2uzo6e8+sEhY7y/zi5RFo22Dy2lFpDw== + +"@rollup/rollup-android-arm64@4.6.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.6.0.tgz#e0cf96960405947c1a09a389467e6aa10ae1a226" + integrity sha512-y3Kt+34smKQNWilicPbBz/MXEY7QwDzMFNgwEWeYiOhUt9MTWKjHqe3EVkXwT2fR7izOvHpDWZ0o2IyD9SWX7A== + +"@rollup/rollup-darwin-arm64@4.6.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.6.0.tgz#6d2f53021fbb9fdecf60bfb6fd5d999aef8385e9" + integrity sha512-oLzzxcUIHltHxOCmaXl+pkIlU+uhSxef5HfntW7RsLh1eHm+vJzjD9Oo4oUKso4YuP4PpbFJNlZjJuOrxo8dPg== + +"@rollup/rollup-darwin-x64@4.6.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.6.0.tgz#b7d0a4bbe6fc493efa269a60a66dc070ac10e2bd" + integrity sha512-+ANnmjkcOBaV25n0+M0Bere3roeVAnwlKW65qagtuAfIxXF9YxUneRyAn/RDcIdRa7QrjRNJL3jR7T43ObGe8Q== + +"@rollup/rollup-linux-arm-gnueabihf@4.6.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.6.0.tgz#12fad1802f500a0196ab0bb4dbb776aaabdedcc7" + integrity sha512-tBTSIkjSVUyrekddpkAqKOosnj1Fc0ZY0rJL2bIEWPKqlEQk0paORL9pUIlt7lcGJi3LzMIlUGXvtNi1Z6MOCQ== + +"@rollup/rollup-linux-arm64-gnu@4.6.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.6.0.tgz#6de1caa2c9952d16dafa21dd26da9562d4ea2112" + integrity sha512-Ed8uJI3kM11de9S0j67wAV07JUNhbAqIrDYhQBrQW42jGopgheyk/cdcshgGO4fW5Wjq97COCY/BHogdGvKVNQ== + +"@rollup/rollup-linux-arm64-musl@4.6.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.6.0.tgz#ef9cae3d22c8c44ff4f271e308bf1c013348bdc0" + integrity sha512-mZoNQ/qK4D7SSY8v6kEsAAyDgznzLLuSFCA3aBHZTmf3HP/dW4tNLTtWh9+LfyO0Z1aUn+ecpT7IQ3WtIg3ViQ== + +"@rollup/rollup-linux-x64-gnu@4.6.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.6.0.tgz#e9071050bed7c64a9fd964cde3c8bd139bf8e489" + integrity sha512-rouezFHpwCqdEXsqAfNsTgSWO0FoZ5hKv5p+TGO5KFhyN/dvYXNMqMolOb8BkyKcPqjYRBeT+Z6V3aM26rPaYg== + +"@rollup/rollup-linux-x64-musl@4.6.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.6.0.tgz#a4c7f5e0c363b2c34f6a7566b1c9da00bf0b96d0" + integrity sha512-Bbm+fyn3S6u51urfj3YnqBXg5vI2jQPncRRELaucmhBVyZkbWClQ1fEsRmdnCPpQOQfkpg9gZArvtMVkOMsh1w== + +"@rollup/rollup-win32-arm64-msvc@4.6.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.6.0.tgz#9a7bfc660ac088d447858fc5223984deb979a55a" + integrity sha512-+MRMcyx9L2kTrTUzYmR61+XVsliMG4odFb5UmqtiT8xOfEicfYAGEuF/D1Pww1+uZkYhBqAHpvju7VN+GnC3ng== + +"@rollup/rollup-win32-ia32-msvc@4.6.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.6.0.tgz#7d5fb96e9f0120451da1fece5c74d2bb373f8925" + integrity sha512-rxfeE6K6s/Xl2HGeK6cO8SiQq3k/3BYpw7cfhW5Bk2euXNEpuzi2cc7llxx1si1QgwfjNtdRNTGqdBzGlFZGFw== + +"@rollup/rollup-win32-x64-msvc@4.6.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.6.0.tgz#15841505c7ec1648020941d04ca0210f88c59e3a" + integrity sha512-QqmCsydHS172Y0Kc13bkMXvipbJSvzeglBncJG3LsYJSiPlxYACz7MmJBs4A8l1oU+jfhYEIC/+AUSlvjmiX/g== "@sinclair/typebox@^0.27.8": version "0.27.8" @@ -2435,32 +2435,32 @@ esbuild-jest@^0: babel-jest "^26.6.3" esbuild@^0.19.3: - version "0.19.7" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.19.7.tgz#b9a7235097b81278dcf090e2532ed13c95a2ee84" - integrity sha512-6brbTZVqxhqgbpqBR5MzErImcpA0SQdoKOkcWK/U30HtQxnokIpG3TX2r0IJqbFUzqLjhU/zC1S5ndgakObVCQ== + version "0.19.8" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.19.8.tgz#ad05b72281d84483fa6b5345bd246c27a207b8f1" + integrity sha512-l7iffQpT2OrZfH2rXIp7/FkmaeZM0vxbxN9KfiCwGYuZqzMg/JdvX26R31Zxn/Pxvsrg3Y9N6XTcnknqDyyv4w== optionalDependencies: - "@esbuild/android-arm" "0.19.7" - "@esbuild/android-arm64" "0.19.7" - "@esbuild/android-x64" "0.19.7" - "@esbuild/darwin-arm64" "0.19.7" - "@esbuild/darwin-x64" "0.19.7" - "@esbuild/freebsd-arm64" "0.19.7" - "@esbuild/freebsd-x64" "0.19.7" - "@esbuild/linux-arm" "0.19.7" - "@esbuild/linux-arm64" "0.19.7" - "@esbuild/linux-ia32" "0.19.7" - "@esbuild/linux-loong64" "0.19.7" - "@esbuild/linux-mips64el" "0.19.7" - "@esbuild/linux-ppc64" "0.19.7" - "@esbuild/linux-riscv64" "0.19.7" - "@esbuild/linux-s390x" "0.19.7" - "@esbuild/linux-x64" "0.19.7" - "@esbuild/netbsd-x64" "0.19.7" - "@esbuild/openbsd-x64" "0.19.7" - "@esbuild/sunos-x64" "0.19.7" - "@esbuild/win32-arm64" "0.19.7" - "@esbuild/win32-ia32" "0.19.7" - "@esbuild/win32-x64" "0.19.7" + "@esbuild/android-arm" "0.19.8" + "@esbuild/android-arm64" "0.19.8" + "@esbuild/android-x64" "0.19.8" + "@esbuild/darwin-arm64" "0.19.8" + "@esbuild/darwin-x64" "0.19.8" + "@esbuild/freebsd-arm64" "0.19.8" + "@esbuild/freebsd-x64" "0.19.8" + "@esbuild/linux-arm" "0.19.8" + "@esbuild/linux-arm64" "0.19.8" + "@esbuild/linux-ia32" "0.19.8" + "@esbuild/linux-loong64" "0.19.8" + "@esbuild/linux-mips64el" "0.19.8" + "@esbuild/linux-ppc64" "0.19.8" + "@esbuild/linux-riscv64" "0.19.8" + "@esbuild/linux-s390x" "0.19.8" + "@esbuild/linux-x64" "0.19.8" + "@esbuild/netbsd-x64" "0.19.8" + "@esbuild/openbsd-x64" "0.19.8" + "@esbuild/sunos-x64" "0.19.8" + "@esbuild/win32-arm64" "0.19.8" + "@esbuild/win32-ia32" "0.19.8" + "@esbuild/win32-x64" "0.19.8" escalade@^3.1.1: version "3.1.1" @@ -4997,22 +4997,22 @@ rimraf@^3.0.2: glob "^7.1.3" rollup@^4.2.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.5.0.tgz#358ee6947fe0e4c8bacdae6896539cade3107655" - integrity sha512-41xsWhzxqjMDASCxH5ibw1mXk+3c4TNI2UjKbLxe6iEzrSQnqOzmmK8/3mufCPbzHNJ2e04Fc1ddI35hHy+8zg== + version "4.6.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.6.0.tgz#4f966f6dd3f6bafd01b864d68ba078d308b864fa" + integrity sha512-R8i5Her4oO1LiMQ3jKf7MUglYV/mhQ5g5OKeld5CnkmPdIGo79FDDQYqPhq/PCVuTQVuxsWgIbDy9F+zdHn80w== optionalDependencies: - "@rollup/rollup-android-arm-eabi" "4.5.0" - "@rollup/rollup-android-arm64" "4.5.0" - "@rollup/rollup-darwin-arm64" "4.5.0" - "@rollup/rollup-darwin-x64" "4.5.0" - "@rollup/rollup-linux-arm-gnueabihf" "4.5.0" - "@rollup/rollup-linux-arm64-gnu" "4.5.0" - "@rollup/rollup-linux-arm64-musl" "4.5.0" - "@rollup/rollup-linux-x64-gnu" "4.5.0" - "@rollup/rollup-linux-x64-musl" "4.5.0" - "@rollup/rollup-win32-arm64-msvc" "4.5.0" - "@rollup/rollup-win32-ia32-msvc" "4.5.0" - "@rollup/rollup-win32-x64-msvc" "4.5.0" + "@rollup/rollup-android-arm-eabi" "4.6.0" + "@rollup/rollup-android-arm64" "4.6.0" + "@rollup/rollup-darwin-arm64" "4.6.0" + "@rollup/rollup-darwin-x64" "4.6.0" + "@rollup/rollup-linux-arm-gnueabihf" "4.6.0" + "@rollup/rollup-linux-arm64-gnu" "4.6.0" + "@rollup/rollup-linux-arm64-musl" "4.6.0" + "@rollup/rollup-linux-x64-gnu" "4.6.0" + "@rollup/rollup-linux-x64-musl" "4.6.0" + "@rollup/rollup-win32-arm64-msvc" "4.6.0" + "@rollup/rollup-win32-ia32-msvc" "4.6.0" + "@rollup/rollup-win32-x64-msvc" "4.6.0" fsevents "~2.3.2" rsvp@^4.8.4: @@ -5645,9 +5645,9 @@ v8-to-istanbul@^9.0.1: convert-source-map "^1.6.0" vite@^5.0.0: - version "5.0.2" - resolved "https://registry.yarnpkg.com/vite/-/vite-5.0.2.tgz#3c94627dace83b9bf04b64eaf618038e30fb95c0" - integrity sha512-6CCq1CAJCNM1ya2ZZA7+jS2KgnhbzvxakmlIjN24cF/PXhRMzpM/z8QgsVJA/Dm5fWUWnVEsmtBoMhmerPxT0g== + version "5.0.4" + resolved "https://registry.yarnpkg.com/vite/-/vite-5.0.4.tgz#d984d2aaa8bac30f1ca9b9eea9b97e052f88c307" + integrity sha512-RzAr8LSvM8lmhB4tQ5OPcBhpjOZRZjuxv9zO5UcxeoY2bd3kP3Ticd40Qma9/BqZ8JS96Ll/jeBX9u+LJZrhVg== dependencies: esbuild "^0.19.3" postcss "^8.4.31" diff --git a/clustercontroller-core/pom.xml b/clustercontroller-core/pom.xml index 8bdfb25e221..7f845a26c73 100644 --- a/clustercontroller-core/pom.xml +++ b/clustercontroller-core/pom.xml @@ -137,6 +137,10 @@ <configuration> <forkCount>4</forkCount> <rerunFailingTestsCount>5</rerunFailingTestsCount> + <systemPropertyVariables> + <!-- Avoid 64 MiB default in favor of just 64 KiB --> + <zookeeper.preAllocSize>64</zookeeper.preAllocSize> + </systemPropertyVariables> </configuration> </plugin> </plugins> diff --git a/configserver-flags/src/main/java/com/yahoo/vespa/configserver/flags/http/DefinedFlag.java b/configserver-flags/src/main/java/com/yahoo/vespa/configserver/flags/http/DefinedFlag.java index 84ba451ac7f..c6e51e530b1 100644 --- a/configserver-flags/src/main/java/com/yahoo/vespa/configserver/flags/http/DefinedFlag.java +++ b/configserver-flags/src/main/java/com/yahoo/vespa/configserver/flags/http/DefinedFlag.java @@ -8,7 +8,6 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import com.yahoo.container.jdisc.HttpResponse; import com.yahoo.jdisc.Response; import com.yahoo.vespa.flags.FlagDefinition; -import com.yahoo.vespa.flags.json.DimensionHelper; import java.io.IOException; import java.io.OutputStream; @@ -42,7 +41,7 @@ public class DefinedFlag extends HttpResponse { definitionNode.put("createdAt", flagDefinition.getCreatedAt().toString()); definitionNode.put("expiresAt", flagDefinition.getExpiresAt().toString()); ArrayNode dimensionsNode = definitionNode.putArray("dimensions"); - flagDefinition.getDimensions().forEach(dimension -> dimensionsNode.add(DimensionHelper.toWire(dimension))); + flagDefinition.getDimensions().forEach(dimension -> dimensionsNode.add(dimension.toWire())); } @Override diff --git a/configserver-flags/src/test/java/com/yahoo/vespa/configserver/flags/db/FlagsDbImplTest.java b/configserver-flags/src/test/java/com/yahoo/vespa/configserver/flags/db/FlagsDbImplTest.java index a82a6f7c599..c9c11e2b0e2 100644 --- a/configserver-flags/src/test/java/com/yahoo/vespa/configserver/flags/db/FlagsDbImplTest.java +++ b/configserver-flags/src/test/java/com/yahoo/vespa/configserver/flags/db/FlagsDbImplTest.java @@ -2,6 +2,7 @@ package com.yahoo.vespa.configserver.flags.db; import com.yahoo.vespa.curator.mock.MockCurator; +import com.yahoo.vespa.flags.Dimension; import com.yahoo.vespa.flags.FetchVector; import com.yahoo.vespa.flags.FlagId; import com.yahoo.vespa.flags.JsonNodeRawFlag; @@ -28,11 +29,11 @@ public class FlagsDbImplTest { MockCurator curator = new MockCurator(); FlagsDbImpl db = new FlagsDbImpl(curator); - var params = new Condition.CreateParams(FetchVector.Dimension.HOSTNAME).withValues("host1"); + var params = new Condition.CreateParams(Dimension.HOSTNAME).withValues("host1"); Condition condition1 = WhitelistCondition.create(params); Rule rule1 = new Rule(Optional.of(JsonNodeRawFlag.fromJson("13")), condition1); FlagId flagId = new FlagId("id"); - FlagData data = new FlagData(flagId, new FetchVector().with(FetchVector.Dimension.ZONE_ID, "zone-a"), rule1); + FlagData data = new FlagData(flagId, new FetchVector().with(Dimension.ZONE_ID, "zone-a"), rule1); db.setValue(flagId, data); Optional<FlagData> dataCopy = db.getValue(flagId); @@ -43,7 +44,7 @@ public class FlagsDbImplTest { dataCopy.get().serializeToJson()); FlagId flagId2 = new FlagId("id2"); - FlagData data2 = new FlagData(flagId2, new FetchVector().with(FetchVector.Dimension.ZONE_ID, "zone-a"), rule1); + FlagData data2 = new FlagData(flagId2, new FetchVector().with(Dimension.ZONE_ID, "zone-a"), rule1); db.setValue(flagId2, data2); Map<FlagId, FlagData> flags = db.getAllFlagData(); assertEquals(flags.size(), 2); diff --git a/configserver-flags/src/test/java/com/yahoo/vespa/configserver/flags/http/FlagsHandlerTest.java b/configserver-flags/src/test/java/com/yahoo/vespa/configserver/flags/http/FlagsHandlerTest.java index 3d37117c002..1e477a6da6e 100644 --- a/configserver-flags/src/test/java/com/yahoo/vespa/configserver/flags/http/FlagsHandlerTest.java +++ b/configserver-flags/src/test/java/com/yahoo/vespa/configserver/flags/http/FlagsHandlerTest.java @@ -8,7 +8,7 @@ import com.yahoo.text.Utf8; import com.yahoo.vespa.configserver.flags.FlagsDb; import com.yahoo.vespa.configserver.flags.db.FlagsDbImpl; import com.yahoo.vespa.curator.mock.MockCurator; -import com.yahoo.vespa.flags.FetchVector; +import com.yahoo.vespa.flags.Dimension; import com.yahoo.vespa.flags.FlagId; import com.yahoo.vespa.flags.Flags; import com.yahoo.vespa.flags.UnboundBooleanFlag; @@ -34,7 +34,7 @@ public class FlagsHandlerTest { "id1", false, List.of("joe"), "2010-01-01", "2030-01-01", "desc1", "mod1"); private static final UnboundBooleanFlag FLAG2 = Flags.defineFeatureFlag( "id2", true, List.of("joe"), "2010-01-01", "2030-01-01", "desc2", "mod2", - FetchVector.Dimension.HOSTNAME, FetchVector.Dimension.INSTANCE_ID); + Dimension.HOSTNAME, Dimension.INSTANCE_ID); private final FlagsDb flagsDb = new FlagsDbImpl(new MockCurator()); private final FlagsHandler handler = new FlagsHandler(FlagsHandler.testContext(), flagsDb); @@ -54,7 +54,7 @@ public class FlagsHandlerTest { void testDefined() { try (Flags.Replacer replacer = Flags.clearFlagsForTesting()) { fixUnusedWarning(replacer); - Flags.defineFeatureFlag("id", false, List.of("joe"), "2010-01-01", "2030-01-01", "desc", "mod", FetchVector.Dimension.HOSTNAME); + Flags.defineFeatureFlag("id", false, List.of("joe"), "2010-01-01", "2030-01-01", "desc", "mod", Dimension.HOSTNAME); verifySuccessfulRequest(Method.GET, "/defined", "", "{\"id\":{\"description\":\"desc\",\"modification-effect\":\"mod\",\"owners\":[\"joe\"],\"createdAt\":\"2010-01-01T00:00:00Z\",\"expiresAt\":\"2030-01-01T00:00:00Z\",\"dimensions\":[\"hostname\"]}}"); diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java b/configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java index 5ac1b685b97..b83a8290cac 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java @@ -48,7 +48,7 @@ import java.util.logging.Level; import java.util.logging.Logger; import static com.yahoo.vespa.curator.Curator.CompletionWaiter; -import static com.yahoo.vespa.flags.FetchVector.Dimension.INSTANCE_ID; +import static com.yahoo.vespa.flags.Dimension.INSTANCE_ID; import static java.util.stream.Collectors.toSet; /** diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java index 76af53eba90..59266dfffaf 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java @@ -28,7 +28,7 @@ import com.yahoo.config.provision.HostName; import com.yahoo.config.provision.Zone; import com.yahoo.container.jdisc.secretstore.SecretStore; import com.yahoo.vespa.config.server.tenant.SecretStoreExternalIdRetriever; -import com.yahoo.vespa.flags.FetchVector; +import com.yahoo.vespa.flags.Dimension; import com.yahoo.vespa.flags.FlagSource; import com.yahoo.vespa.flags.Flags; import com.yahoo.vespa.flags.PermanentFlags; @@ -46,7 +46,7 @@ import java.util.concurrent.ExecutorService; import java.util.function.Predicate; import static com.yahoo.vespa.config.server.ConfigServerSpec.fromConfig; -import static com.yahoo.vespa.flags.FetchVector.Dimension.CLUSTER_TYPE; +import static com.yahoo.vespa.flags.Dimension.CLUSTER_TYPE; /** * Implementation of {@link ModelContext} for configserver. @@ -307,10 +307,10 @@ public class ModelContextImpl implements ModelContext { private static <V> V flagValue(FlagSource source, ApplicationId appId, Version vespaVersion, UnboundFlag<? extends V, ?, ?> flag) { return flag.bindTo(source) - .with(FetchVector.Dimension.INSTANCE_ID, appId.serializedForm()) - .with(FetchVector.Dimension.APPLICATION, appId.toSerializedFormWithoutInstance()) - .with(FetchVector.Dimension.VESPA_VERSION, vespaVersion.toFullString()) - .with(FetchVector.Dimension.TENANT_ID, appId.tenant().value()) + .with(Dimension.INSTANCE_ID, appId.serializedForm()) + .with(Dimension.APPLICATION, appId.toSerializedFormWithoutInstance()) + .with(Dimension.VESPA_VERSION, vespaVersion.toFullString()) + .with(Dimension.TENANT_ID, appId.tenant().value()) .boxedValue(); } @@ -320,10 +320,10 @@ public class ModelContextImpl implements ModelContext { ClusterSpec.Type clusterType, UnboundFlag<? extends V, ?, ?> flag) { return flag.bindTo(source) - .with(FetchVector.Dimension.INSTANCE_ID, appId.serializedForm()) - .with(FetchVector.Dimension.APPLICATION, appId.toSerializedFormWithoutInstance()) - .with(FetchVector.Dimension.CLUSTER_TYPE, clusterType.name()) - .with(FetchVector.Dimension.VESPA_VERSION, vespaVersion.toFullString()) + .with(Dimension.INSTANCE_ID, appId.serializedForm()) + .with(Dimension.APPLICATION, appId.toSerializedFormWithoutInstance()) + .with(Dimension.CLUSTER_TYPE, clusterType.name()) + .with(Dimension.VESPA_VERSION, vespaVersion.toFullString()) .boxedValue(); } @@ -333,10 +333,10 @@ public class ModelContextImpl implements ModelContext { ClusterSpec.Id clusterId, UnboundFlag<? extends V, ?, ?> flag) { return flag.bindTo(source) - .with(FetchVector.Dimension.INSTANCE_ID, appId.serializedForm()) - .with(FetchVector.Dimension.APPLICATION, appId.toSerializedFormWithoutInstance()) - .with(FetchVector.Dimension.CLUSTER_ID, clusterId.value()) - .with(FetchVector.Dimension.VESPA_VERSION, vespaVersion.toFullString()) + .with(Dimension.INSTANCE_ID, appId.serializedForm()) + .with(Dimension.APPLICATION, appId.toSerializedFormWithoutInstance()) + .with(Dimension.CLUSTER_ID, clusterId.value()) + .with(Dimension.VESPA_VERSION, vespaVersion.toFullString()) .boxedValue(); } @@ -411,8 +411,8 @@ public class ModelContextImpl implements ModelContext { this.tenantSecretStores = tenantSecretStores; this.secretStore = secretStore; this.jvmGCOptionsFlag = PermanentFlags.JVM_GC_OPTIONS.bindTo(flagSource) - .with(FetchVector.Dimension.INSTANCE_ID, applicationId.serializedForm()) - .with(FetchVector.Dimension.APPLICATION, applicationId.toSerializedFormWithoutInstance()); + .with(Dimension.INSTANCE_ID, applicationId.serializedForm()) + .with(Dimension.APPLICATION, applicationId.toSerializedFormWithoutInstance()); this.allowDisableMtls = flagValue(flagSource, applicationId, PermanentFlags.ALLOW_DISABLE_MTLS); this.operatorCertificates = operatorCertificates; this.tlsCiphersOverride = flagValue(flagSource, applicationId, PermanentFlags.TLS_CIPHERS_OVERRIDE); @@ -523,8 +523,8 @@ public class ModelContextImpl implements ModelContext { private static <V> V flagValue(FlagSource source, ApplicationId appId, UnboundFlag<? extends V, ?, ?> flag) { return flag.bindTo(source) - .with(FetchVector.Dimension.INSTANCE_ID, appId.serializedForm()) - .with(FetchVector.Dimension.APPLICATION, appId.toSerializedFormWithoutInstance()) + .with(Dimension.INSTANCE_ID, appId.serializedForm()) + .with(Dimension.APPLICATION, appId.toSerializedFormWithoutInstance()) .boxedValue(); } } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionRepository.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionRepository.java index 99d5d23a87c..47b8215b52d 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionRepository.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionRepository.java @@ -83,7 +83,7 @@ import java.util.logging.Level; import java.util.logging.Logger; import static com.yahoo.vespa.curator.Curator.CompletionWaiter; -import static com.yahoo.vespa.flags.FetchVector.Dimension.INSTANCE_ID; +import static com.yahoo.vespa.flags.Dimension.INSTANCE_ID; import static java.nio.file.Files.readAttributes; /** diff --git a/container-search/src/main/java/com/yahoo/search/searchers/RateLimitingSearcher.java b/container-search/src/main/java/com/yahoo/search/searchers/RateLimitingSearcher.java index 104db4ea731..90e9897556f 100755 --- a/container-search/src/main/java/com/yahoo/search/searchers/RateLimitingSearcher.java +++ b/container-search/src/main/java/com/yahoo/search/searchers/RateLimitingSearcher.java @@ -31,7 +31,9 @@ import java.util.concurrent.ThreadLocalRandom; * <li>rate.id - (String) the id of the client from rate limiting perspective * <li>rate.cost - (Double) the cost Double of this query. This is read after executing the query and hence can be set * by downstream searchers inspecting the result to allow differencing the cost of various queries. Default is 1. - * <li>rate.quota - (Double) the cost per second a particular id is allowed to consume in this system. + * <li>rate.quota - (Double) the cost per second a particular id is allowed to consume. By default this is across + * all nodes of the cluster (i.e, this is invariant with cluster size), set the config variable + * localRate to true to make this be rate per node. * <li>rate.idDimension - (String) the name of the rate-id dimension used when logging metrics. * If this is not specified, the metric will be logged without dimensions. * <li>rate.dryRun - (Boolean) emit metrics on rejected requests but don't actually reject them @@ -69,6 +71,8 @@ public class RateLimitingSearcher extends Searcher { /** Shared capacity across all threads. Each thread will ask for more capacity from here when they run out. */ private final AvailableCapacity availableCapacity; + private final boolean localRate; + /** Capacity already allocated to this thread */ private final ThreadLocal<Map<String, Double>> allocatedCapacity = new ThreadLocal<>(); @@ -90,10 +94,14 @@ public class RateLimitingSearcher extends Searcher { } /** For testing - allows injection of a timer to avoid depending on the system clock */ - public RateLimitingSearcher(RateLimitingConfig rateLimitingConfig, ClusterInfoConfig clusterInfoConfig, MetricReceiver metric, Clock clock) { + public RateLimitingSearcher(RateLimitingConfig rateLimitingConfig, + ClusterInfoConfig clusterInfoConfig, + MetricReceiver metric, + Clock clock) { this.capacityIncrement = rateLimitingConfig.capacityIncrement(); this.recheckForCapacityProbability = rateLimitingConfig.recheckForCapacityProbability(); this.availableCapacity = new AvailableCapacity(rateLimitingConfig.maxAvailableCapacity(), clock); + this.localRate = rateLimitingConfig.localRate(); this.nodeCount = clusterInfoConfig.nodeCount(); @@ -109,7 +117,8 @@ public class RateLimitingSearcher extends Searcher { return execution.search(query); } - rate = rate / nodeCount; + if ( ! localRate) + rate = rate / nodeCount; if (allocatedCapacity.get() == null) // new thread allocatedCapacity.set(new HashMap<>()); @@ -122,7 +131,7 @@ public class RateLimitingSearcher extends Searcher { requestCapacity(id, rate); } - if (rate==0 || getAllocatedCapacity(id) <= 0) { // we are still over rate: reject + if (rate == 0 || getAllocatedCapacity(id) <= 0) { // we are still over rate: reject String idDim = query.properties().getString(idDimensionKey, null); if (idDim == null) { overQuotaCounter.add(1); diff --git a/container-search/src/main/resources/configdefinitions/search.config.rate-limiting.def b/container-search/src/main/resources/configdefinitions/search.config.rate-limiting.def index e5d2f5f9ed4..81ef06868ce 100644 --- a/container-search/src/main/resources/configdefinitions/search.config.rate-limiting.def +++ b/container-search/src/main/resources/configdefinitions/search.config.rate-limiting.def @@ -17,3 +17,6 @@ maxAvailableCapacity double default=10000 # A good number may be 1 / (maxAvailableCapacity * average-cost) recheckForCapacityProbability double default=0.001 +# Set to true to interpret the rate.quota given in the query as a node-local value +# instead of a cluster-wide value. +localRate bool default=false diff --git a/container-search/src/test/java/com/yahoo/search/searchers/test/RateLimitingSearcherTestCase.java b/container-search/src/test/java/com/yahoo/search/searchers/test/RateLimitingSearcherTestCase.java index 22b8d8f4d76..1682bd37fb6 100755 --- a/container-search/src/test/java/com/yahoo/search/searchers/test/RateLimitingSearcherTestCase.java +++ b/container-search/src/test/java/com/yahoo/search/searchers/test/RateLimitingSearcherTestCase.java @@ -31,23 +31,10 @@ public class RateLimitingSearcherTestCase { @Test void testRateLimiting() { - RateLimitingConfig.Builder rateLimitingConfig = new RateLimitingConfig.Builder(); - rateLimitingConfig.maxAvailableCapacity(4); - rateLimitingConfig.capacityIncrement(2); - rateLimitingConfig.recheckForCapacityProbability(1.0); - - ClusterInfoConfig.Builder clusterInfoConfig = new ClusterInfoConfig.Builder(); - clusterInfoConfig.clusterId("testCluster"); - clusterInfoConfig.nodeCount(4); - ManualClock clock = new ManualClock(); MetricReceiver.MockReceiver metric = new MetricReceiver.MockReceiver(); - - Chain<Searcher> chain = new Chain<>("test", new RateLimitingSearcher(new RateLimitingConfig(rateLimitingConfig), - new ClusterInfoConfig(clusterInfoConfig), - metric, clock), - new CostSettingSearcher()); - assertEquals(2, tryRequests(chain, "id1"), "'rate' request are available initially"); + var chain = createChain(false, clock, metric); + assertEquals(2, tryRequests(chain, "id1"), "'rate/nodes' request are available initially"); assertTrue(executeWasAllowed(chain, "id1", true), "However, don't reject if we dryRun"); clock.advance(Duration.ofMillis(1500)); // causes 2 new requests to become available assertEquals(2, tryRequests(chain, "id1"), "'rate' new requests became available"); @@ -76,6 +63,34 @@ public class RateLimitingSearcherTestCase { assertEquals(requestsToTry - 2 + requestsToTry - 4, map.get(metric.point("id", "id2")).getCount()); } + @Test + void testLocalRateLimiting() { + ManualClock clock = new ManualClock(); + MetricReceiver.MockReceiver metric = new MetricReceiver.MockReceiver(); + var chain = createChain(true, clock, metric); + + assertEquals(9, tryRequests(chain, "id1"), "'rate' request are available initially"); + } + + private Chain<Searcher> createChain(boolean localRate, ManualClock clock, MetricReceiver.MockReceiver metric) { + RateLimitingConfig.Builder rateLimitingConfig = new RateLimitingConfig.Builder(); + rateLimitingConfig.maxAvailableCapacity(4); + rateLimitingConfig.capacityIncrement(2); + rateLimitingConfig.recheckForCapacityProbability(1.0); + rateLimitingConfig.localRate(localRate); + + ClusterInfoConfig.Builder clusterInfoConfig = new ClusterInfoConfig.Builder(); + clusterInfoConfig.clusterId("testCluster"); + clusterInfoConfig.nodeCount(4); + + + return new Chain<>("test", new RateLimitingSearcher(new RateLimitingConfig(rateLimitingConfig), + new ClusterInfoConfig(clusterInfoConfig), + metric, + clock), + new CostSettingSearcher()); + } + private int requestsToTry = 50; /** diff --git a/dependency-versions/pom.xml b/dependency-versions/pom.xml index 1c99b1dc115..4c42349e31f 100644 --- a/dependency-versions/pom.xml +++ b/dependency-versions/pom.xml @@ -37,8 +37,8 @@ <error-prone-annotations.vespa.version>2.23.0</error-prone-annotations.vespa.version> <guava.vespa.version>32.1.3-jre</guava.vespa.version> <guice.vespa.version>6.0.0</guice.vespa.version> - <jackson2.vespa.version>2.15.3</jackson2.vespa.version> - <jackson-databind.vespa.version>2.15.3</jackson-databind.vespa.version> + <jackson2.vespa.version>2.16.0</jackson2.vespa.version> + <jackson-databind.vespa.version>${jackson2.vespa.version}</jackson-databind.vespa.version> <jakarta.inject.vespa.version>2.0.1</jakarta.inject.vespa.version> <javax.inject.vespa.version>1</javax.inject.vespa.version> <javax.servlet-api.vespa.version>3.1.0</javax.servlet-api.vespa.version> diff --git a/dist/vespa.spec b/dist/vespa.spec index bdae7bdcced..b89d19e5c36 100644 --- a/dist/vespa.spec +++ b/dist/vespa.spec @@ -501,8 +501,6 @@ fi %dir %attr(-,%{_vespa_user},%{_vespa_group}) %{_prefix}/logs/vespa/search %{_prefix}/man %{_prefix}/sbin -%{_prefix}/share -%exclude %{_prefix}/share/cmake %dir %attr(-,%{_vespa_user},%{_vespa_group}) %{_prefix}/var %dir %attr(-,%{_vespa_user},%{_vespa_group}) %{_prefix}/var/crash %dir %attr(-,%{_vespa_user},%{_vespa_group}) %{_prefix}/var/db @@ -556,6 +554,8 @@ fi %{_prefix}/libexec/vespa/vespa-wrapper %{_prefix}/libexec/vespa/find-pid %{_prefix}/libexec/vespa/vespa-curl-wrapper +%{_prefix}/share +%exclude %{_prefix}/share/cmake %files base-libs %if %{_defattr_is_vespa_vespa} diff --git a/eval/src/apps/eval_expr/eval_expr.cpp b/eval/src/apps/eval_expr/eval_expr.cpp index 23af5a926c4..af7dd26ca26 100644 --- a/eval/src/apps/eval_expr/eval_expr.cpp +++ b/eval/src/apps/eval_expr/eval_expr.cpp @@ -406,6 +406,7 @@ int main(int argc, char **argv) { } Context ctx; if ((expr_cnt == 1) && (vespalib::string(argv[expr_idx]) == "interactive")) { + setlocale(LC_ALL, ""); return interactive_mode(ctx); } if ((expr_cnt == 1) && (vespalib::string(argv[expr_idx]) == "json-repl")) { diff --git a/flags/src/main/java/com/yahoo/vespa/flags/Dimension.java b/flags/src/main/java/com/yahoo/vespa/flags/Dimension.java new file mode 100644 index 00000000000..0f81fd4640b --- /dev/null +++ b/flags/src/main/java/com/yahoo/vespa/flags/Dimension.java @@ -0,0 +1,120 @@ +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.flags; + +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * Flag dimensions. + * + * <ol> + * <li>A flag definition declares the dimensions it supports.*</li> + * <li>To <em>get</em> the value of a flag, a {@link FetchVector} should be built with the same set of dimensions.*</li> + * <li>To <em>set</em> the value of a flag, add a flag data <em>rule</em> with that value. The rule may be + * contain conditions that refer to these dimension.</li> + * </ol> + * + * <p>*) The system, cloud, environment, and zone dimensions are special: A flag should NOT list them in the + * flag definition (1),** and the dimensions are automatically set (2),**. These dimensions may always be referred to + * when overriding values, either as dimensions (3) or in dedicated files.</p> + * <p>**) The controller may want different flag values depending on cloud, environment, and/or zone. + * Disregard (*) for those dimensions: The relevant dimensions should be declared in the flag definition (1), + * and specified when getting the value (2).</p> + * + * @author hakonhall + */ +public enum Dimension { + /** + * Application from ApplicationId::toSerializedFormWithoutInstance() of the form tenant:applicationName. + * <p><em>WARNING: NOT ApplicationId</em> - see {@link #INSTANCE_ID}.</p> + */ + APPLICATION("application"), + + /** Machine architecture: either arm64 or x86_64. */ + ARCHITECTURE("architecture"), + + /** Whether "enclave" (or "inclave" or "exclave"), or not ("noclave"). */ + CLAVE("clave"), + + /** + * Cloud from com.yahoo.config.provision.CloudName::value, e.g. yahoo, aws, gcp. + * + * <p><em>Eager resolution</em>: This dimension is resolved before putting the flag data to the config server + * or controller, unless controller and the flag has declared this dimension. + */ + CLOUD("cloud"), + + /** Cloud account ID from com.yahoo.config.provision.CloudAccount::value, e.g. aws:123456789012 */ + CLOUD_ACCOUNT("cloud-account"), + + /** Cluster ID from com.yahoo.config.provision.ClusterSpec.Id::value, e.g. cluster-controllers, logserver. */ + CLUSTER_ID("cluster-id"), + + /** Cluster type from com.yahoo.config.provision.ClusterSpec.Type::name, e.g. content, container, admin */ + CLUSTER_TYPE("cluster-type"), + + /** Email address of user - provided by auth0 in console. */ + CONSOLE_USER_EMAIL("console-user-email"), + + /** Hosted Vespa environment from com.yahoo.config.provision.Environment::value, e.g. prod, staging, test. */ + ENVIRONMENT("environment"), + + /** + * Fully qualified hostname. + * + * <p>NOTE: There is seldom any need to set HOSTNAME, as it is always set implicitly (in {@link Flags}) + * from {@code Defaults.getDefaults().vespaHostname()}. The hostname may e.g. be overridden when + * fetching flag value for a Docker container node. + */ + HOSTNAME("hostname"), + + /** Value from ApplicationId::serializedForm of the form tenant:applicationName:instance. */ + INSTANCE_ID("instance"), + + /** Node type from com.yahoo.config.provision.NodeType::name, e.g. tenant, host, confighost, controller, etc. */ + NODE_TYPE("node-type"), + + /** + * Hosted Vespa system from com.yahoo.config.provision.SystemName::value, e.g. main, cd, public, publiccd. + * <em>Eager resolution</em>, see {@link #CLOUD}. + */ + SYSTEM("system"), + + /** Value from TenantName::value, e.g. vespa-team */ + TENANT_ID("tenant"), + + /** + * Vespa version from Version::toFullString of the form Major.Minor.Micro. + * + * <p>NOTE: There is seldom any need to set VESPA_VERSION, as it is always set implicitly + * (in {@link Flags}) from {@link com.yahoo.component.Vtag#currentVersion}. The version COULD e.g. + * be overridden when fetching flag value for a Docker container node. + */ + VESPA_VERSION("vespa-version"), + + /** + * Virtual zone ID from com.yahoo.config.provision.zone.ZoneId::value of the form environment.region, + * see com.yahoo.config.provision.zone.ZoneApi::getVirtualId. <em>Eager resolution</em>, see {@link #CLOUD}. + */ + ZONE_ID("zone"); + + private final String wireName; + + private static final Map<String, Dimension> dimensionsByWireName = + Stream.of(values()).collect(Collectors.toMap(x -> x.wireName, Function.identity())); + + public static Dimension fromWire(String wireName) { + Dimension dimension = dimensionsByWireName.get(wireName); + if (dimension == null) { + throw new IllegalArgumentException("Unknown serialized dimension: '" + wireName + "'"); + } + + return dimension; + } + + Dimension(String wireName) { this.wireName = wireName; } + + public String toWire() { return wireName; } +} diff --git a/flags/src/main/java/com/yahoo/vespa/flags/FetchVector.java b/flags/src/main/java/com/yahoo/vespa/flags/FetchVector.java index b5a944430f3..5639cbc0143 100644 --- a/flags/src/main/java/com/yahoo/vespa/flags/FetchVector.java +++ b/flags/src/main/java/com/yahoo/vespa/flags/FetchVector.java @@ -1,8 +1,6 @@ // Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.flags; -import com.yahoo.vespa.flags.json.DimensionHelper; - import java.util.Collection; import java.util.EnumMap; import java.util.Map; @@ -18,80 +16,6 @@ import java.util.function.Consumer; * @author hakonhall */ public class FetchVector { - /** - * Note: If this enum is changed, you must also change {@link DimensionHelper}. - */ - public enum Dimension { - /** - * Application from ApplicationId::toSerializedFormWithoutInstance() of the form tenant:applicationName. - * <p><em>WARNING: NOT ApplicationId</em> - see {@link #INSTANCE_ID}.</p> - */ - APPLICATION, - - /** - * Cloud from com.yahoo.config.provision.CloudName::value, e.g. yahoo, aws, gcp. - * - * <p><em>Eager resolution</em>: This dimension is resolved before putting the flag data to the config server - * or controller, unless controller and the flag has declared this dimension. - */ - CLOUD, - - /** - * Cloud account ID from com.yahoo.config.provision.CloudAccount::value, e.g. aws:123456789012 - */ - CLOUD_ACCOUNT, - - /** Cluster ID from com.yahoo.config.provision.ClusterSpec.Id::value, e.g. cluster-controllers, logserver. */ - CLUSTER_ID, - - /** Cluster type from com.yahoo.config.provision.ClusterSpec.Type::name, e.g. content, container, admin */ - CLUSTER_TYPE, - - /** Email address of user - provided by auth0 in console. */ - CONSOLE_USER_EMAIL, - - /** Hosted Vespa environment from com.yahoo.config.provision.Environment::value, e.g. prod, staging, test. */ - ENVIRONMENT, - - /** - * Fully qualified hostname. - * - * <p>NOTE: There is seldom any need to set HOSTNAME, as it is always set implicitly (in {@link Flags}) - * from {@code Defaults.getDefaults().vespaHostname()}. The hostname may e.g. be overridden when - * fetching flag value for a Docker container node. - */ - HOSTNAME, - - /** Value from ApplicationId::serializedForm of the form tenant:applicationName:instance. */ - INSTANCE_ID, - - /** Node type from com.yahoo.config.provision.NodeType::name, e.g. tenant, host, confighost, controller, etc. */ - NODE_TYPE, - - /** - * Hosted Vespa system from com.yahoo.config.provision.SystemName::value, e.g. main, cd, public, publiccd. - * <em>Eager resolution</em>, see {@link #CLOUD}. - */ - SYSTEM, - - /** Value from TenantName::value, e.g. vespa-team */ - TENANT_ID, - - /** - * Vespa version from Version::toFullString of the form Major.Minor.Micro. - * - * <p>NOTE: There is seldom any need to set VESPA_VERSION, as it is always set implicitly - * (in {@link Flags}) from {@link com.yahoo.component.Vtag#currentVersion}. The version COULD e.g. - * be overridden when fetching flag value for a Docker container node. - */ - VESPA_VERSION, - - /** - * Virtual zone ID from com.yahoo.config.provision.zone.ZoneId::value of the form environment.region, - * see com.yahoo.config.provision.zone.ZoneApi::getVirtualId. <em>Eager resolution</em>, see {@link #CLOUD}. - */ - ZONE_ID - } private final Map<Dimension, String> map; @@ -115,7 +39,7 @@ public class FetchVector { public boolean isEmpty() { return map.isEmpty(); } - public boolean hasDimension(FetchVector.Dimension dimension) { return map.containsKey(dimension);} + public boolean hasDimension(Dimension dimension) { return map.containsKey(dimension);} public Set<Dimension> dimensions() { return map.keySet(); } diff --git a/flags/src/main/java/com/yahoo/vespa/flags/Flag.java b/flags/src/main/java/com/yahoo/vespa/flags/Flag.java index 0ca9dbb4cf7..7ca5066969f 100644 --- a/flags/src/main/java/com/yahoo/vespa/flags/Flag.java +++ b/flags/src/main/java/com/yahoo/vespa/flags/Flag.java @@ -21,10 +21,10 @@ public interface Flag<T, F> { FlagSerializer<T> serializer(); /** Returns an immutable clone of the current object, except with the dimension set accordingly. */ - F with(FetchVector.Dimension dimension, String dimensionValue); + F with(Dimension dimension, String dimensionValue); - /** Same as {@link #with(FetchVector.Dimension, String)} if value is present, and otherwise returns {@code this}. */ - default F with(FetchVector.Dimension dimension, Optional<String> dimensionValue) { + /** Same as {@link #with(Dimension, String)} if value is present, and otherwise returns {@code this}. */ + default F with(Dimension dimension, Optional<String> dimensionValue) { return dimensionValue.map(value -> with(dimension, value)).orElse(self()); } diff --git a/flags/src/main/java/com/yahoo/vespa/flags/FlagDefinition.java b/flags/src/main/java/com/yahoo/vespa/flags/FlagDefinition.java index 837bc3b6e11..181c7ebd066 100644 --- a/flags/src/main/java/com/yahoo/vespa/flags/FlagDefinition.java +++ b/flags/src/main/java/com/yahoo/vespa/flags/FlagDefinition.java @@ -16,7 +16,7 @@ public class FlagDefinition { private final Instant expiresAt; private final String description; private final String modificationEffect; - private final List<FetchVector.Dimension> dimensions; + private final List<Dimension> dimensions; public FlagDefinition( UnboundFlag<?, ?, ?> unboundFlag, @@ -25,7 +25,7 @@ public class FlagDefinition { Instant expiresAt, String description, String modificationEffect, - FetchVector.Dimension... dimensions) { + Dimension... dimensions) { this.unboundFlag = unboundFlag; this.owners = owners; this.createdAt = createdAt; @@ -40,7 +40,7 @@ public class FlagDefinition { return unboundFlag; } - public List<FetchVector.Dimension> getDimensions() { + public List<Dimension> getDimensions() { return dimensions; } @@ -58,7 +58,7 @@ public class FlagDefinition { public Instant getExpiresAt() { return expiresAt; } - private static void validate(List<String> owners, Instant createdAt, Instant expiresAt, List<FetchVector.Dimension> dimensions) { + private static void validate(List<String> owners, Instant createdAt, Instant expiresAt, List<Dimension> dimensions) { if (expiresAt.isBefore(createdAt)) { throw new IllegalArgumentException( String.format( @@ -74,14 +74,14 @@ public class FlagDefinition { throw new IllegalArgumentException("Owner(s) must be specified"); } - if (dimensions.contains(FetchVector.Dimension.CONSOLE_USER_EMAIL)) { - Set<FetchVector.Dimension> disallowedCombinations = EnumSet.allOf(FetchVector.Dimension.class); - disallowedCombinations.remove(FetchVector.Dimension.CONSOLE_USER_EMAIL); - disallowedCombinations.remove(FetchVector.Dimension.INSTANCE_ID); - disallowedCombinations.remove(FetchVector.Dimension.TENANT_ID); + if (dimensions.contains(Dimension.CONSOLE_USER_EMAIL)) { + Set<Dimension> disallowedCombinations = EnumSet.allOf(Dimension.class); + disallowedCombinations.remove(Dimension.CONSOLE_USER_EMAIL); + disallowedCombinations.remove(Dimension.INSTANCE_ID); + disallowedCombinations.remove(Dimension.TENANT_ID); disallowedCombinations.retainAll(dimensions); if (!disallowedCombinations.isEmpty()) - throw new IllegalArgumentException("Dimension " + FetchVector.Dimension.CONSOLE_USER_EMAIL + " cannot be combined with " + disallowedCombinations); + throw new IllegalArgumentException("Dimension " + Dimension.CONSOLE_USER_EMAIL + " cannot be combined with " + disallowedCombinations); } } } diff --git a/flags/src/main/java/com/yahoo/vespa/flags/FlagImpl.java b/flags/src/main/java/com/yahoo/vespa/flags/FlagImpl.java index 1b0464be7c6..496217c1e58 100644 --- a/flags/src/main/java/com/yahoo/vespa/flags/FlagImpl.java +++ b/flags/src/main/java/com/yahoo/vespa/flags/FlagImpl.java @@ -31,7 +31,7 @@ public abstract class FlagImpl<T, F extends FlagImpl<T, F>> implements Flag<T, F } @Override - public F with(FetchVector.Dimension dimension, String dimensionValue) { + public F with(Dimension dimension, String dimensionValue) { return factory.create(id, defaultValue, fetchVector.with(dimension, dimensionValue), serializer, source); } diff --git a/flags/src/main/java/com/yahoo/vespa/flags/Flags.java b/flags/src/main/java/com/yahoo/vespa/flags/Flags.java index f4096cc343f..7d62826a3a2 100644 --- a/flags/src/main/java/com/yahoo/vespa/flags/Flags.java +++ b/flags/src/main/java/com/yahoo/vespa/flags/Flags.java @@ -13,14 +13,16 @@ import java.util.Optional; import java.util.TreeMap; import java.util.function.Predicate; -import static com.yahoo.vespa.flags.FetchVector.Dimension.APPLICATION; -import static com.yahoo.vespa.flags.FetchVector.Dimension.CLOUD_ACCOUNT; -import static com.yahoo.vespa.flags.FetchVector.Dimension.CONSOLE_USER_EMAIL; -import static com.yahoo.vespa.flags.FetchVector.Dimension.HOSTNAME; -import static com.yahoo.vespa.flags.FetchVector.Dimension.INSTANCE_ID; -import static com.yahoo.vespa.flags.FetchVector.Dimension.NODE_TYPE; -import static com.yahoo.vespa.flags.FetchVector.Dimension.TENANT_ID; -import static com.yahoo.vespa.flags.FetchVector.Dimension.VESPA_VERSION; +import static com.yahoo.vespa.flags.Dimension.APPLICATION; +import static com.yahoo.vespa.flags.Dimension.ARCHITECTURE; +import static com.yahoo.vespa.flags.Dimension.CLAVE; +import static com.yahoo.vespa.flags.Dimension.CLOUD_ACCOUNT; +import static com.yahoo.vespa.flags.Dimension.CONSOLE_USER_EMAIL; +import static com.yahoo.vespa.flags.Dimension.HOSTNAME; +import static com.yahoo.vespa.flags.Dimension.INSTANCE_ID; +import static com.yahoo.vespa.flags.Dimension.NODE_TYPE; +import static com.yahoo.vespa.flags.Dimension.TENANT_ID; +import static com.yahoo.vespa.flags.Dimension.VESPA_VERSION; /** * Definitions of feature flags. @@ -34,8 +36,8 @@ import static com.yahoo.vespa.flags.FetchVector.Dimension.VESPA_VERSION; * an unbound flag to a flag source produces a (bound) flag, e.g. {@link BooleanFlag} and {@link StringFlag}.</li> * <li>If you would like your flag value to be dependent on e.g. the application ID, then 1. you should * declare this in the unbound flag definition in this file (referring to - * {@link FetchVector.Dimension#INSTANCE_ID}), and 2. specify the application ID when retrieving the value, e.g. - * {@link BooleanFlag#with(FetchVector.Dimension, String)}. See {@link FetchVector} for more info.</li> + * {@link Dimension#INSTANCE_ID}), and 2. specify the application ID when retrieving the value, e.g. + * {@link BooleanFlag#with(Dimension, String)}. See {@link FetchVector} for more info.</li> * </ol> * * <p>Once the code is in place, you can override the flag value. This depends on the flag source, but typically @@ -76,6 +78,15 @@ public class Flags { "Takes effect at redeployment (requires restart)", INSTANCE_ID); + public static final UnboundStringFlag NESSUS_AGENT_GROUP = defineStringFlag( + "nessus-agent-group", "All", + List.of("hakonhall"), "2023-11-29", "2023-12-29", + "Either run nessusagent as before (All), or link against \"vespa-ci\"," + + " or disable the nessusagent (empty string \"\")", + "Takes effect after host admin restart", + (String value) -> value.equals("All") || value.equals("vespa-ci") || value.isEmpty(), + ARCHITECTURE, CLAVE); + public static final UnboundIntFlag MAX_UNCOMMITTED_MEMORY = defineIntFlag( "max-uncommitted-memory", 130000, List.of("geirst, baldersheim"), "2021-10-21", "2023-12-31", @@ -296,7 +307,7 @@ public class Flags { NODE_TYPE, HOSTNAME); public static final UnboundBooleanFlag ENABLE_THE_ONE_THAT_SHOULD_NOT_BE_NAMED = defineFeatureFlag( - "enable-the-one-that-should-not-be-named", false, List.of("hmusum"), "2023-05-08", "2023-12-01", + "enable-the-one-that-should-not-be-named", false, List.of("hmusum"), "2023-05-08", "2024-01-15", "Whether to enable the one program that should not be named", "Takes effect at next host-admin tick"); @@ -315,13 +326,13 @@ public class Flags { public static final UnboundBooleanFlag WRITE_CONFIG_SERVER_SESSION_DATA_AS_ONE_BLOB = defineFeatureFlag( "write-config-server-session-data-as-blob", false, - List.of("hmusum"), "2023-07-19", "2024-01-01", + List.of("hmusum"), "2023-07-19", "2024-02-01", "Whether to write config server session data in one blob or as individual paths", "Takes effect immediately"); public static final UnboundBooleanFlag READ_CONFIG_SERVER_SESSION_DATA_AS_ONE_BLOB = defineFeatureFlag( "read-config-server-session-data-as-blob", false, - List.of("hmusum"), "2023-07-19", "2024-01-01", + List.of("hmusum"), "2023-07-19", "2024-02-01", "Whether to read config server session data from session data blob or from individual paths", "Takes effect immediately"); @@ -363,7 +374,7 @@ public class Flags { public static final UnboundStringFlag UNKNOWN_CONFIG_DEFINITION = defineStringFlag( "unknown-config-definition", "warn", - List.of("hmusum"), "2023-09-25", "2024-01-01", + List.of("hmusum"), "2023-09-25", "2024-02-01", "How to handle user config referencing unknown config definitions. Valid values are 'warn' and 'fail'", "Takes effect at redeployment", INSTANCE_ID); @@ -407,17 +418,24 @@ public class Flags { "Takes effect at redeployment", INSTANCE_ID); + public static final UnboundBooleanFlag ENABLE_NEW_PAYMENT_METHOD_FLOW = defineFeatureFlag( + "enable-new-payment-method-flow", false, + List.of("bjorncs"), "2023-11-29", "2024-03-01", + "Whether to enable the new billing flow", + "Takes effect immediately", + TENANT_ID, CONSOLE_USER_EMAIL); + /** WARNING: public for testing: All flags should be defined in {@link Flags}. */ public static UnboundBooleanFlag defineFeatureFlag(String flagId, boolean defaultValue, List<String> owners, String createdAt, String expiresAt, String description, - String modificationEffect, FetchVector.Dimension... dimensions) { + String modificationEffect, Dimension... dimensions) { return define(UnboundBooleanFlag::new, flagId, defaultValue, owners, createdAt, expiresAt, description, modificationEffect, dimensions); } /** WARNING: public for testing: All flags should be defined in {@link Flags}. */ public static UnboundStringFlag defineStringFlag(String flagId, String defaultValue, List<String> owners, String createdAt, String expiresAt, String description, - String modificationEffect, FetchVector.Dimension... dimensions) { + String modificationEffect, Dimension... dimensions) { return defineStringFlag(flagId, defaultValue, owners, createdAt, expiresAt, description, modificationEffect, value -> true, @@ -428,7 +446,7 @@ public class Flags { public static UnboundStringFlag defineStringFlag(String flagId, String defaultValue, List<String> owners, String createdAt, String expiresAt, String description, String modificationEffect, Predicate<String> validator, - FetchVector.Dimension... dimensions) { + Dimension... dimensions) { return define((i, d, v) -> new UnboundStringFlag(i, d, v, validator), flagId, defaultValue, owners, createdAt, expiresAt, description, modificationEffect, dimensions); } @@ -436,28 +454,28 @@ public class Flags { /** WARNING: public for testing: All flags should be defined in {@link Flags}. */ public static UnboundIntFlag defineIntFlag(String flagId, int defaultValue, List<String> owners, String createdAt, String expiresAt, String description, - String modificationEffect, FetchVector.Dimension... dimensions) { + String modificationEffect, Dimension... dimensions) { return define(UnboundIntFlag::new, flagId, defaultValue, owners, createdAt, expiresAt, description, modificationEffect, dimensions); } /** WARNING: public for testing: All flags should be defined in {@link Flags}. */ public static UnboundLongFlag defineLongFlag(String flagId, long defaultValue, List<String> owners, String createdAt, String expiresAt, String description, - String modificationEffect, FetchVector.Dimension... dimensions) { + String modificationEffect, Dimension... dimensions) { return define(UnboundLongFlag::new, flagId, defaultValue, owners, createdAt, expiresAt, description, modificationEffect, dimensions); } /** WARNING: public for testing: All flags should be defined in {@link Flags}. */ public static UnboundDoubleFlag defineDoubleFlag(String flagId, double defaultValue, List<String> owners, String createdAt, String expiresAt, String description, - String modificationEffect, FetchVector.Dimension... dimensions) { + String modificationEffect, Dimension... dimensions) { return define(UnboundDoubleFlag::new, flagId, defaultValue, owners, createdAt, expiresAt, description, modificationEffect, dimensions); } /** WARNING: public for testing: All flags should be defined in {@link Flags}. */ public static <T> UnboundJacksonFlag<T> defineJacksonFlag(String flagId, T defaultValue, Class<T> jacksonClass, List<String> owners, String createdAt, String expiresAt, String description, - String modificationEffect, FetchVector.Dimension... dimensions) { + String modificationEffect, Dimension... dimensions) { return define((id2, defaultValue2, vector2) -> new UnboundJacksonFlag<>(id2, defaultValue2, vector2, jacksonClass), flagId, defaultValue, owners, createdAt, expiresAt, description, modificationEffect, dimensions); } @@ -465,7 +483,7 @@ public class Flags { /** WARNING: public for testing: All flags should be defined in {@link Flags}. */ public static <T> UnboundListFlag<T> defineListFlag(String flagId, List<T> defaultValue, Class<T> elementClass, List<String> owners, String createdAt, String expiresAt, - String description, String modificationEffect, FetchVector.Dimension... dimensions) { + String description, String modificationEffect, Dimension... dimensions) { return define((fid, dval, fvec) -> new UnboundListFlag<>(fid, dval, elementClass, fvec), flagId, defaultValue, owners, createdAt, expiresAt, description, modificationEffect, dimensions); } @@ -500,8 +518,8 @@ public class Flags { * use them in the controller in this way. * @param <T> The boxed type of the flag value, e.g. Boolean for flags guarding features. * @param <U> The type of the unbound flag, e.g. UnboundBooleanFlag. - * @return An unbound flag with {@link FetchVector.Dimension#HOSTNAME HOSTNAME} and - * {@link FetchVector.Dimension#VESPA_VERSION VESPA_VERSION} already set. The ZONE environment + * @return An unbound flag with {@link Dimension#HOSTNAME HOSTNAME} and + * {@link Dimension#VESPA_VERSION VESPA_VERSION} already set. The ZONE environment * is typically implicit. */ private static <T, U extends UnboundFlag<?, ?, ?>> U define(TypedUnboundFlagFactory<T, U> factory, @@ -512,7 +530,7 @@ public class Flags { String expiresAt, String description, String modificationEffect, - FetchVector.Dimension[] dimensions) { + Dimension[] dimensions) { FlagId id = new FlagId(flagId); FetchVector vector = new FetchVector() .with(HOSTNAME, Defaults.getDefaults().vespaHostname()) diff --git a/flags/src/main/java/com/yahoo/vespa/flags/PermanentFlags.java b/flags/src/main/java/com/yahoo/vespa/flags/PermanentFlags.java index 1c50cc54964..acebca05fdb 100644 --- a/flags/src/main/java/com/yahoo/vespa/flags/PermanentFlags.java +++ b/flags/src/main/java/com/yahoo/vespa/flags/PermanentFlags.java @@ -13,15 +13,15 @@ import java.util.Set; import java.util.function.Predicate; import java.util.regex.Pattern; -import static com.yahoo.vespa.flags.FetchVector.Dimension.INSTANCE_ID; -import static com.yahoo.vespa.flags.FetchVector.Dimension.CLUSTER_ID; -import static com.yahoo.vespa.flags.FetchVector.Dimension.CLUSTER_TYPE; -import static com.yahoo.vespa.flags.FetchVector.Dimension.CONSOLE_USER_EMAIL; -import static com.yahoo.vespa.flags.FetchVector.Dimension.HOSTNAME; -import static com.yahoo.vespa.flags.FetchVector.Dimension.NODE_TYPE; -import static com.yahoo.vespa.flags.FetchVector.Dimension.TENANT_ID; -import static com.yahoo.vespa.flags.FetchVector.Dimension.VESPA_VERSION; -import static com.yahoo.vespa.flags.FetchVector.Dimension.ZONE_ID; +import static com.yahoo.vespa.flags.Dimension.INSTANCE_ID; +import static com.yahoo.vespa.flags.Dimension.CLUSTER_ID; +import static com.yahoo.vespa.flags.Dimension.CLUSTER_TYPE; +import static com.yahoo.vespa.flags.Dimension.CONSOLE_USER_EMAIL; +import static com.yahoo.vespa.flags.Dimension.HOSTNAME; +import static com.yahoo.vespa.flags.Dimension.NODE_TYPE; +import static com.yahoo.vespa.flags.Dimension.TENANT_ID; +import static com.yahoo.vespa.flags.Dimension.VESPA_VERSION; +import static com.yahoo.vespa.flags.Dimension.ZONE_ID; /** * Definition for permanent feature flags @@ -417,42 +417,42 @@ public class PermanentFlags { private PermanentFlags() {} private static UnboundBooleanFlag defineFeatureFlag( - String flagId, boolean defaultValue, String description, String modificationEffect, FetchVector.Dimension... dimensions) { + String flagId, boolean defaultValue, String description, String modificationEffect, Dimension... dimensions) { return Flags.defineFeatureFlag(flagId, defaultValue, OWNERS, toString(CREATED_AT), toString(EXPIRES_AT), description, modificationEffect, dimensions); } private static UnboundStringFlag defineStringFlag( - String flagId, String defaultValue, String description, String modificationEffect, FetchVector.Dimension... dimensions) { + String flagId, String defaultValue, String description, String modificationEffect, Dimension... dimensions) { return Flags.defineStringFlag(flagId, defaultValue, OWNERS, toString(CREATED_AT), toString(EXPIRES_AT), description, modificationEffect, dimensions); } private static UnboundStringFlag defineStringFlag( - String flagId, String defaultValue, String description, String modificationEffect, Predicate<String> validator, FetchVector.Dimension... dimensions) { + String flagId, String defaultValue, String description, String modificationEffect, Predicate<String> validator, Dimension... dimensions) { return Flags.defineStringFlag(flagId, defaultValue, OWNERS, toString(CREATED_AT), toString(EXPIRES_AT), description, modificationEffect, validator, dimensions); } private static UnboundIntFlag defineIntFlag( - String flagId, int defaultValue, String description, String modificationEffect, FetchVector.Dimension... dimensions) { + String flagId, int defaultValue, String description, String modificationEffect, Dimension... dimensions) { return Flags.defineIntFlag(flagId, defaultValue, OWNERS, toString(CREATED_AT), toString(EXPIRES_AT), description, modificationEffect, dimensions); } private static UnboundLongFlag defineLongFlag( - String flagId, long defaultValue, String description, String modificationEffect, FetchVector.Dimension... dimensions) { + String flagId, long defaultValue, String description, String modificationEffect, Dimension... dimensions) { return Flags.defineLongFlag(flagId, defaultValue, OWNERS, toString(CREATED_AT), toString(EXPIRES_AT), description, modificationEffect, dimensions); } private static UnboundDoubleFlag defineDoubleFlag( - String flagId, double defaultValue, String description, String modificationEffect, FetchVector.Dimension... dimensions) { + String flagId, double defaultValue, String description, String modificationEffect, Dimension... dimensions) { return Flags.defineDoubleFlag(flagId, defaultValue, OWNERS, toString(CREATED_AT), toString(EXPIRES_AT), description, modificationEffect, dimensions); } private static <T> UnboundJacksonFlag<T> defineJacksonFlag( - String flagId, T defaultValue, Class<T> jacksonClass, String description, String modificationEffect, FetchVector.Dimension... dimensions) { + String flagId, T defaultValue, Class<T> jacksonClass, String description, String modificationEffect, Dimension... dimensions) { return Flags.defineJacksonFlag(flagId, defaultValue, jacksonClass, OWNERS, toString(CREATED_AT), toString(EXPIRES_AT), description, modificationEffect, dimensions); } private static <T> UnboundListFlag<T> defineListFlag( - String flagId, List<T> defaultValue, Class<T> elementClass, String description, String modificationEffect, FetchVector.Dimension... dimensions) { + String flagId, List<T> defaultValue, Class<T> elementClass, String description, String modificationEffect, Dimension... dimensions) { return Flags.defineListFlag(flagId, defaultValue, elementClass, OWNERS, toString(CREATED_AT), toString(EXPIRES_AT), description, modificationEffect, dimensions); } diff --git a/flags/src/main/java/com/yahoo/vespa/flags/UnboundFlag.java b/flags/src/main/java/com/yahoo/vespa/flags/UnboundFlag.java index edde650adc9..f6d4e080e82 100644 --- a/flags/src/main/java/com/yahoo/vespa/flags/UnboundFlag.java +++ b/flags/src/main/java/com/yahoo/vespa/flags/UnboundFlag.java @@ -18,7 +18,7 @@ public interface UnboundFlag<T, F extends Flag<T, F>, U extends UnboundFlag<T, F FlagSerializer<T> serializer(); /** Returns a clone of the unbound flag, but with the dimension set accordingly. */ - U with(FetchVector.Dimension dimension, String dimensionValue); + U with(Dimension dimension, String dimensionValue); /** Binds to a flag source, returning a (bound) flag. */ F bindTo(FlagSource source); diff --git a/flags/src/main/java/com/yahoo/vespa/flags/UnboundFlagImpl.java b/flags/src/main/java/com/yahoo/vespa/flags/UnboundFlagImpl.java index a079bf734d7..d8936e17395 100644 --- a/flags/src/main/java/com/yahoo/vespa/flags/UnboundFlagImpl.java +++ b/flags/src/main/java/com/yahoo/vespa/flags/UnboundFlagImpl.java @@ -42,7 +42,7 @@ public abstract class UnboundFlagImpl<T, F extends Flag<T, F>, U extends Unbound } @Override - public U with(FetchVector.Dimension dimension, String dimensionValue) { + public U with(Dimension dimension, String dimensionValue) { return unboundFlagFactory.create(id, defaultValue, defaultFetchVector.with(dimension, dimensionValue)); } diff --git a/flags/src/main/java/com/yahoo/vespa/flags/json/Condition.java b/flags/src/main/java/com/yahoo/vespa/flags/json/Condition.java index 2881e9ab9ad..247987e68f4 100644 --- a/flags/src/main/java/com/yahoo/vespa/flags/json/Condition.java +++ b/flags/src/main/java/com/yahoo/vespa/flags/json/Condition.java @@ -1,6 +1,7 @@ // Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.flags.json; +import com.yahoo.vespa.flags.Dimension; import com.yahoo.vespa.flags.FetchVector; import com.yahoo.vespa.flags.json.wire.WireCondition; @@ -32,11 +33,11 @@ public interface Condition extends Predicate<FetchVector> { } class CreateParams { - private final FetchVector.Dimension dimension; + private final Dimension dimension; private List<String> values = List.of(); private Optional<String> predicate = Optional.empty(); - public CreateParams(FetchVector.Dimension dimension) { this.dimension = Objects.requireNonNull(dimension); } + public CreateParams(Dimension dimension) { this.dimension = Objects.requireNonNull(dimension); } public CreateParams withValues(String... values) { return withValues(List.of(values)); } public CreateParams withValues(List<String> values) { @@ -49,7 +50,7 @@ public interface Condition extends Predicate<FetchVector> { return this; } - public FetchVector.Dimension dimension() { return dimension; } + public Dimension dimension() { return dimension; } public List<String> values() { return values; } public Optional<String> predicate() { return predicate; } @@ -69,7 +70,7 @@ public interface Condition extends Predicate<FetchVector> { Condition.Type type = Condition.Type.fromWire(wireCondition.type); Objects.requireNonNull(wireCondition.dimension); - FetchVector.Dimension dimension = DimensionHelper.fromWire(wireCondition.dimension); + Dimension dimension = Dimension.fromWire(wireCondition.dimension); var params = new CreateParams(dimension); if (wireCondition.values != null) { @@ -85,7 +86,7 @@ public interface Condition extends Predicate<FetchVector> { Condition.Type type(); - FetchVector.Dimension dimension(); + Dimension dimension(); CreateParams toCreateParams(); diff --git a/flags/src/main/java/com/yahoo/vespa/flags/json/DimensionHelper.java b/flags/src/main/java/com/yahoo/vespa/flags/json/DimensionHelper.java deleted file mode 100644 index 7298f090be2..00000000000 --- a/flags/src/main/java/com/yahoo/vespa/flags/json/DimensionHelper.java +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.flags.json; - -import com.yahoo.vespa.flags.FetchVector; - -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * @author hakonhall - */ -public class DimensionHelper { - - private static final Map<FetchVector.Dimension, String> serializedDimensions = new HashMap<>(); - - static { - // WARNING: If you ever change the serialized form of a dimension, ensure the new serialized - // flag data are pushed out everywhere before removing support for old format, see VESPA-27760. - serializedDimensions.put(FetchVector.Dimension.APPLICATION, "application"); - serializedDimensions.put(FetchVector.Dimension.CLOUD, "cloud"); - serializedDimensions.put(FetchVector.Dimension.CLOUD_ACCOUNT, "cloud-account"); - serializedDimensions.put(FetchVector.Dimension.CLUSTER_ID, "cluster-id"); - serializedDimensions.put(FetchVector.Dimension.CLUSTER_TYPE, "cluster-type"); - serializedDimensions.put(FetchVector.Dimension.CONSOLE_USER_EMAIL, "console-user-email"); - serializedDimensions.put(FetchVector.Dimension.ENVIRONMENT, "environment"); - serializedDimensions.put(FetchVector.Dimension.HOSTNAME, "hostname"); - serializedDimensions.put(FetchVector.Dimension.INSTANCE_ID, "instance"); - serializedDimensions.put(FetchVector.Dimension.NODE_TYPE, "node-type"); - serializedDimensions.put(FetchVector.Dimension.SYSTEM, "system"); - serializedDimensions.put(FetchVector.Dimension.TENANT_ID, "tenant"); - serializedDimensions.put(FetchVector.Dimension.VESPA_VERSION, "vespa-version"); - serializedDimensions.put(FetchVector.Dimension.ZONE_ID, "zone"); - - if (serializedDimensions.size() != FetchVector.Dimension.values().length) { - throw new IllegalStateException(FetchVectorHelper.class.getName() + " is not in sync with " + - FetchVector.Dimension.class.getName()); - } - } - - private static final Map<String, FetchVector.Dimension> deserializedDimensions = serializedDimensions. - entrySet().stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey)); - - public static String toWire(FetchVector.Dimension dimension) { - String serializedDimension = serializedDimensions.get(dimension); - if (serializedDimension == null) { - throw new IllegalArgumentException("Unsupported dimension (please add it): '" + dimension + "'"); - } - - return serializedDimension; - } - - public static FetchVector.Dimension fromWire(String serializedDimension) { - FetchVector.Dimension dimension = deserializedDimensions.get(serializedDimension); - if (dimension == null) { - throw new IllegalArgumentException("Unknown serialized dimension: '" + serializedDimension + "'"); - } - - return dimension; - } - - private DimensionHelper() { } - -} diff --git a/flags/src/main/java/com/yahoo/vespa/flags/json/FetchVectorHelper.java b/flags/src/main/java/com/yahoo/vespa/flags/json/FetchVectorHelper.java index 31ba0e1e6cf..97ea4695481 100644 --- a/flags/src/main/java/com/yahoo/vespa/flags/json/FetchVectorHelper.java +++ b/flags/src/main/java/com/yahoo/vespa/flags/json/FetchVectorHelper.java @@ -1,6 +1,7 @@ // Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.flags.json; +import com.yahoo.vespa.flags.Dimension; import com.yahoo.vespa.flags.FetchVector; import java.util.Map; @@ -12,17 +13,17 @@ import java.util.stream.Collectors; public class FetchVectorHelper { public static Map<String, String> toWire(FetchVector vector) { - Map<FetchVector.Dimension, String> map = vector.toMap(); + Map<Dimension, String> map = vector.toMap(); if (map.isEmpty()) return null; return map.entrySet().stream().collect(Collectors.toMap( - entry -> DimensionHelper.toWire(entry.getKey()), + entry -> entry.getKey().toWire(), Map.Entry::getValue)); } public static FetchVector fromWire(Map<String, String> wireMap) { if (wireMap == null) return new FetchVector(); return FetchVector.fromMap(wireMap.entrySet().stream().collect(Collectors.toMap( - entry -> DimensionHelper.fromWire(entry.getKey()), + entry -> Dimension.fromWire(entry.getKey()), Map.Entry::getValue))); } diff --git a/flags/src/main/java/com/yahoo/vespa/flags/json/ListCondition.java b/flags/src/main/java/com/yahoo/vespa/flags/json/ListCondition.java index 12a10298787..7e71bb10a46 100644 --- a/flags/src/main/java/com/yahoo/vespa/flags/json/ListCondition.java +++ b/flags/src/main/java/com/yahoo/vespa/flags/json/ListCondition.java @@ -1,6 +1,7 @@ // Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.flags.json; +import com.yahoo.vespa.flags.Dimension; import com.yahoo.vespa.flags.FetchVector; import com.yahoo.vespa.flags.json.wire.WireCondition; @@ -12,7 +13,7 @@ import java.util.Objects; */ public abstract class ListCondition implements Condition { private final Condition.Type type; - private final FetchVector.Dimension dimension; + private final Dimension dimension; private final List<String> values; private final boolean isWhitelist; @@ -33,7 +34,7 @@ public abstract class ListCondition implements Condition { } @Override - public FetchVector.Dimension dimension() { + public Dimension dimension() { return dimension; } @@ -52,7 +53,7 @@ public abstract class ListCondition implements Condition { public WireCondition toWire() { var condition = new WireCondition(); condition.type = type.toWire(); - condition.dimension = DimensionHelper.toWire(dimension); + condition.dimension = dimension.toWire(); condition.values = values.isEmpty() ? null : values; return condition; } diff --git a/flags/src/main/java/com/yahoo/vespa/flags/json/RelationalCondition.java b/flags/src/main/java/com/yahoo/vespa/flags/json/RelationalCondition.java index 49dc7c75752..18d1052d43c 100644 --- a/flags/src/main/java/com/yahoo/vespa/flags/json/RelationalCondition.java +++ b/flags/src/main/java/com/yahoo/vespa/flags/json/RelationalCondition.java @@ -2,6 +2,7 @@ package com.yahoo.vespa.flags.json; import com.yahoo.component.Version; +import com.yahoo.vespa.flags.Dimension; import com.yahoo.vespa.flags.FetchVector; import com.yahoo.vespa.flags.json.wire.WireCondition; @@ -14,7 +15,7 @@ import java.util.function.Predicate; public class RelationalCondition implements Condition { private final RelationalPredicate relationalPredicate; private final Predicate<String> predicate; - private final FetchVector.Dimension dimension; + private final Dimension dimension; public static RelationalCondition create(CreateParams params) { if (!params.values().isEmpty()) { @@ -37,12 +38,12 @@ public class RelationalCondition implements Condition { return new RelationalCondition(relationalPredicate, p, params.dimension()); default: throw new IllegalArgumentException(RelationalCondition.class.getSimpleName() + - " not supported for dimension " + FetchVector.Dimension.VESPA_VERSION.name()); + " not supported for dimension " + Dimension.VESPA_VERSION.name()); } } private RelationalCondition(RelationalPredicate relationalPredicate, Predicate<String> predicate, - FetchVector.Dimension dimension) { + Dimension dimension) { this.relationalPredicate = relationalPredicate; this.predicate = predicate; this.dimension = dimension; @@ -54,7 +55,7 @@ public class RelationalCondition implements Condition { } @Override - public FetchVector.Dimension dimension() { + public Dimension dimension() { return dimension; } @@ -76,7 +77,7 @@ public class RelationalCondition implements Condition { public WireCondition toWire() { var condition = new WireCondition(); condition.type = Condition.Type.RELATIONAL.toWire(); - condition.dimension = DimensionHelper.toWire(dimension); + condition.dimension = dimension.toWire(); condition.predicate = relationalPredicate.toWire(); return condition; } diff --git a/flags/src/test/java/com/yahoo/vespa/flags/DimensionTest.java b/flags/src/test/java/com/yahoo/vespa/flags/DimensionTest.java new file mode 100644 index 00000000000..11687265a05 --- /dev/null +++ b/flags/src/test/java/com/yahoo/vespa/flags/DimensionTest.java @@ -0,0 +1,25 @@ +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.flags; + +/** + * @author hakonhall + */ +class DimensionTest { + /** + * A compile-time test: If this breaks you have most likely added (or removed) a dimension? + * If so you need to update the following:</p> + * + * <ul> + * <li>Dimension validation in SystemFlagsDataArchive</li> + * <li>Flag edit documenting dimension list in EditFlagDataCommandTest</li> + * </ul> + */ + @SuppressWarnings("unused") + public String remember_to_update_SystemFlagsDataArchive(Dimension dimension) { + return switch (dimension) { + case APPLICATION, ARCHITECTURE, CLAVE, CLOUD, CLOUD_ACCOUNT, CLUSTER_ID, CLUSTER_TYPE, + CONSOLE_USER_EMAIL, ENVIRONMENT, HOSTNAME, INSTANCE_ID, NODE_TYPE, SYSTEM, TENANT_ID, + VESPA_VERSION, ZONE_ID -> dimension.toWire(); + }; + } +}
\ No newline at end of file diff --git a/flags/src/test/java/com/yahoo/vespa/flags/FlagsTest.java b/flags/src/test/java/com/yahoo/vespa/flags/FlagsTest.java index d3a5406bead..d48e8ec9c8b 100644 --- a/flags/src/test/java/com/yahoo/vespa/flags/FlagsTest.java +++ b/flags/src/test/java/com/yahoo/vespa/flags/FlagsTest.java @@ -32,8 +32,8 @@ public class FlagsTest { final boolean defaultValue = false; FlagSource source = mock(FlagSource.class); BooleanFlag booleanFlag = Flags.defineFeatureFlag("id", defaultValue, List.of("owner"), "1970-01-01", "2100-01-01", "description", - "modification effect", FetchVector.Dimension.ZONE_ID, FetchVector.Dimension.HOSTNAME) - .with(FetchVector.Dimension.ZONE_ID, "a-zone") + "modification effect", Dimension.ZONE_ID, Dimension.HOSTNAME) + .with(Dimension.ZONE_ID, "a-zone") .bindTo(source); assertThat(booleanFlag.id().toString(), equalTo("id")); @@ -44,31 +44,31 @@ public class FlagsTest { ArgumentCaptor<FetchVector> vector = ArgumentCaptor.forClass(FetchVector.class); verify(source).fetch(any(), vector.capture()); // hostname is set by default - Optional<String> hostname = vector.getValue().getValue(FetchVector.Dimension.HOSTNAME); + Optional<String> hostname = vector.getValue().getValue(Dimension.HOSTNAME); assertTrue(hostname.isPresent()); assertFalse(hostname.get().isEmpty()); // zone is set because it was set on the unbound flag above - assertThat(vector.getValue().getValue(FetchVector.Dimension.ZONE_ID), is(Optional.of("a-zone"))); + assertThat(vector.getValue().getValue(Dimension.ZONE_ID), is(Optional.of("a-zone"))); // application and node type are not set - assertThat(vector.getValue().getValue(FetchVector.Dimension.INSTANCE_ID), is(Optional.empty())); - assertThat(vector.getValue().getValue(FetchVector.Dimension.NODE_TYPE), is(Optional.empty())); + assertThat(vector.getValue().getValue(Dimension.INSTANCE_ID), is(Optional.empty())); + assertThat(vector.getValue().getValue(Dimension.NODE_TYPE), is(Optional.empty())); RawFlag rawFlag = mock(RawFlag.class); when(source.fetch(eq(new FlagId("id")), any())).thenReturn(Optional.of(rawFlag)); when(rawFlag.asJsonNode()).thenReturn(BooleanNode.getTrue()); // raw flag deserializes to true - assertThat(booleanFlag.with(FetchVector.Dimension.INSTANCE_ID, "an-app").value(), equalTo(true)); + assertThat(booleanFlag.with(Dimension.INSTANCE_ID, "an-app").value(), equalTo(true)); verify(source, times(2)).fetch(any(), vector.capture()); // application was set on the (bound) flag. - assertThat(vector.getValue().getValue(FetchVector.Dimension.INSTANCE_ID), is(Optional.of("an-app"))); + assertThat(vector.getValue().getValue(Dimension.INSTANCE_ID), is(Optional.of("an-app"))); } @Test void testString() { testGeneric(Flags.defineStringFlag("string-id", "default value", List.of("owner"), "1970-01-01", "2100-01-01", "description", - "modification effect", FetchVector.Dimension.ZONE_ID, FetchVector.Dimension.HOSTNAME), + "modification effect", Dimension.ZONE_ID, Dimension.HOSTNAME), "other value"); } @@ -100,7 +100,7 @@ public class FlagsTest { instance.string = "foo"; testGeneric(Flags.defineJacksonFlag("jackson-id", defaultInstance, ExampleJacksonClass.class, - List.of("owner"), "1970-01-01", "2100-01-01", "description", "modification effect", FetchVector.Dimension.HOSTNAME), + List.of("owner"), "1970-01-01", "2100-01-01", "description", "modification effect", Dimension.HOSTNAME), instance); testGeneric(Flags.defineListFlag("jackson-list-id", List.of(defaultInstance), ExampleJacksonClass.class, List.of("owner"), "1970-01-01", "2100-01-01", "desc", "mod"), diff --git a/flags/src/test/java/com/yahoo/vespa/flags/file/FlagDbFileTest.java b/flags/src/test/java/com/yahoo/vespa/flags/file/FlagDbFileTest.java index 8bf0014cbfe..4ea4f8ab638 100644 --- a/flags/src/test/java/com/yahoo/vespa/flags/file/FlagDbFileTest.java +++ b/flags/src/test/java/com/yahoo/vespa/flags/file/FlagDbFileTest.java @@ -1,6 +1,7 @@ // Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.flags.file; +import com.yahoo.vespa.flags.Dimension; import com.yahoo.vespa.flags.FetchVector; import com.yahoo.vespa.flags.FlagId; import com.yahoo.vespa.flags.json.FlagData; @@ -55,7 +56,7 @@ public class FlagDbFileTest { // Changing value of id1, removing id2, adding id3 dataMap.remove(id2); - FlagData newData1 = new FlagData(id1, new FetchVector().with(FetchVector.Dimension.HOSTNAME, "h1")); + FlagData newData1 = new FlagData(id1, new FetchVector().with(Dimension.HOSTNAME, "h1")); dataMap.put(id1, newData1); FlagId id3 = new FlagId("id3"); FlagData data3 = new FlagData(id3, new FetchVector()); diff --git a/flags/src/test/java/com/yahoo/vespa/flags/json/ConditionTest.java b/flags/src/test/java/com/yahoo/vespa/flags/json/ConditionTest.java index a1cc2e99cbc..b283cfef0a5 100644 --- a/flags/src/test/java/com/yahoo/vespa/flags/json/ConditionTest.java +++ b/flags/src/test/java/com/yahoo/vespa/flags/json/ConditionTest.java @@ -1,6 +1,7 @@ // Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.flags.json; +import com.yahoo.vespa.flags.Dimension; import com.yahoo.vespa.flags.FetchVector; import org.junit.jupiter.api.Test; @@ -15,23 +16,23 @@ public class ConditionTest { @Test void testWhitelist() { String hostname1 = "host1"; - var params = new Condition.CreateParams(FetchVector.Dimension.HOSTNAME).withValues(hostname1); + var params = new Condition.CreateParams(Dimension.HOSTNAME).withValues(hostname1); Condition condition = WhitelistCondition.create(params); assertFalse(condition.test(new FetchVector())); - assertFalse(condition.test(new FetchVector().with(FetchVector.Dimension.INSTANCE_ID, "foo"))); - assertFalse(condition.test(new FetchVector().with(FetchVector.Dimension.HOSTNAME, "bar"))); - assertTrue(condition.test(new FetchVector().with(FetchVector.Dimension.HOSTNAME, hostname1))); + assertFalse(condition.test(new FetchVector().with(Dimension.INSTANCE_ID, "foo"))); + assertFalse(condition.test(new FetchVector().with(Dimension.HOSTNAME, "bar"))); + assertTrue(condition.test(new FetchVector().with(Dimension.HOSTNAME, hostname1))); } @Test void testBlacklist() { String hostname1 = "host1"; - var params = new Condition.CreateParams(FetchVector.Dimension.HOSTNAME).withValues(hostname1); + var params = new Condition.CreateParams(Dimension.HOSTNAME).withValues(hostname1); Condition condition = BlacklistCondition.create(params); assertTrue(condition.test(new FetchVector())); - assertTrue(condition.test(new FetchVector().with(FetchVector.Dimension.INSTANCE_ID, "foo"))); - assertTrue(condition.test(new FetchVector().with(FetchVector.Dimension.HOSTNAME, "bar"))); - assertFalse(condition.test(new FetchVector().with(FetchVector.Dimension.HOSTNAME, hostname1))); + assertTrue(condition.test(new FetchVector().with(Dimension.INSTANCE_ID, "foo"))); + assertTrue(condition.test(new FetchVector().with(Dimension.HOSTNAME, "bar"))); + assertFalse(condition.test(new FetchVector().with(Dimension.HOSTNAME, hostname1))); } @Test @@ -44,7 +45,7 @@ public class ConditionTest { // Test with empty fetch vector along vespa version dimension (this should never happen as the // version is always available through Vtag, although Vtag has a dummy version number for e.g. // locally run unit tests that hasn't set the release Vespa version). - var params = new Condition.CreateParams(FetchVector.Dimension.VESPA_VERSION).withPredicate(">=7.1.2"); + var params = new Condition.CreateParams(Dimension.VESPA_VERSION).withPredicate(">=7.1.2"); Condition condition = RelationalCondition.create(params); assertFalse(condition.test(new FetchVector())); } @@ -56,8 +57,8 @@ public class ConditionTest { } private boolean vespaVersionCondition(String vespaVersion, String predicate) { - var params = new Condition.CreateParams(FetchVector.Dimension.VESPA_VERSION).withPredicate(predicate); + var params = new Condition.CreateParams(Dimension.VESPA_VERSION).withPredicate(predicate); Condition condition = RelationalCondition.create(params); - return condition.test(new FetchVector().with(FetchVector.Dimension.VESPA_VERSION, vespaVersion)); + return condition.test(new FetchVector().with(Dimension.VESPA_VERSION, vespaVersion)); } } diff --git a/flags/src/test/java/com/yahoo/vespa/flags/json/FlagDataTest.java b/flags/src/test/java/com/yahoo/vespa/flags/json/FlagDataTest.java index 98c99231237..d19d262e593 100644 --- a/flags/src/test/java/com/yahoo/vespa/flags/json/FlagDataTest.java +++ b/flags/src/test/java/com/yahoo/vespa/flags/json/FlagDataTest.java @@ -2,6 +2,7 @@ package com.yahoo.vespa.flags.json; import com.yahoo.text.JSON; +import com.yahoo.vespa.flags.Dimension; import com.yahoo.vespa.flags.FetchVector; import com.yahoo.vespa.flags.RawFlag; import org.junit.jupiter.api.Test; @@ -61,27 +62,27 @@ public class FlagDataTest { // First rule matches only if both conditions match verify(Optional.of("false"), vector - .with(FetchVector.Dimension.HOSTNAME, "host1") - .with(FetchVector.Dimension.INSTANCE_ID, "app2")); + .with(Dimension.HOSTNAME, "host1") + .with(Dimension.INSTANCE_ID, "app2")); verify(Optional.of("true"), vector - .with(FetchVector.Dimension.HOSTNAME, "host1") - .with(FetchVector.Dimension.INSTANCE_ID, "app3")); + .with(Dimension.HOSTNAME, "host1") + .with(Dimension.INSTANCE_ID, "app3")); // Verify unsetting a dimension with null works. verify(Optional.of("true"), vector - .with(FetchVector.Dimension.HOSTNAME, "host1") - .with(FetchVector.Dimension.INSTANCE_ID, "app3") - .with(FetchVector.Dimension.INSTANCE_ID, null)); + .with(Dimension.HOSTNAME, "host1") + .with(Dimension.INSTANCE_ID, "app3") + .with(Dimension.INSTANCE_ID, null)); // No rules apply if zone is overridden to an unknown zone - verify(Optional.empty(), vector.with(FetchVector.Dimension.ZONE_ID, "unknown zone")); + verify(Optional.empty(), vector.with(Dimension.ZONE_ID, "unknown zone")); } @Test void testPartialResolve() { FlagData data = FlagData.deserialize(json); assertEquals(data.partialResolve(vector), data); - assertEquals(data.partialResolve(vector.with(FetchVector.Dimension.INSTANCE_ID, "app1")), + assertEquals(data.partialResolve(vector.with(Dimension.INSTANCE_ID, "app1")), FlagData.deserialize(""" { "id": "id1", @@ -102,7 +103,7 @@ public class FlagDataTest { } }""")); - assertEquals(data.partialResolve(vector.with(FetchVector.Dimension.INSTANCE_ID, "app1")), + assertEquals(data.partialResolve(vector.with(Dimension.INSTANCE_ID, "app1")), FlagData.deserialize(""" { "id": "id1", @@ -123,7 +124,7 @@ public class FlagDataTest { } }""")); - assertEquals(data.partialResolve(vector.with(FetchVector.Dimension.INSTANCE_ID, "app3")), + assertEquals(data.partialResolve(vector.with(Dimension.INSTANCE_ID, "app3")), FlagData.deserialize(""" { "id": "id1", @@ -154,8 +155,8 @@ public class FlagDataTest { } }""")); - assertEquals(data.partialResolve(vector.with(FetchVector.Dimension.INSTANCE_ID, "app3") - .with(FetchVector.Dimension.HOSTNAME, "host1")), + assertEquals(data.partialResolve(vector.with(Dimension.INSTANCE_ID, "app3") + .with(Dimension.HOSTNAME, "host1")), FlagData.deserialize(""" { "id": "id1", @@ -169,8 +170,8 @@ public class FlagDataTest { } }""")); - assertEquals(data.partialResolve(vector.with(FetchVector.Dimension.INSTANCE_ID, "app3") - .with(FetchVector.Dimension.HOSTNAME, "host3")), + assertEquals(data.partialResolve(vector.with(Dimension.INSTANCE_ID, "app3") + .with(Dimension.HOSTNAME, "host3")), FlagData.deserialize(""" { "id": "id1", @@ -191,9 +192,9 @@ public class FlagDataTest { } }""")); - assertEquals(data.partialResolve(vector.with(FetchVector.Dimension.INSTANCE_ID, "app3") - .with(FetchVector.Dimension.HOSTNAME, "host3") - .with(FetchVector.Dimension.ZONE_ID, "zone2")), + assertEquals(data.partialResolve(vector.with(Dimension.INSTANCE_ID, "app3") + .with(Dimension.HOSTNAME, "host3") + .with(Dimension.ZONE_ID, "zone2")), FlagData.deserialize(""" { "id": "id1", @@ -204,9 +205,9 @@ public class FlagDataTest { ] }""")); - FlagData fullyResolved = data.partialResolve(vector.with(FetchVector.Dimension.INSTANCE_ID, "app3") - .with(FetchVector.Dimension.HOSTNAME, "host3") - .with(FetchVector.Dimension.ZONE_ID, "zone3")); + FlagData fullyResolved = data.partialResolve(vector.with(Dimension.INSTANCE_ID, "app3") + .with(Dimension.HOSTNAME, "host3") + .with(Dimension.ZONE_ID, "zone3")); assertEquals(fullyResolved, FlagData.deserialize(""" { "id": "id1" @@ -265,7 +266,7 @@ public class FlagDataTest { }"""; FlagData data = FlagData.deserialize(json); assertTrue(JSON.equals(data.serializeToJson(), json)); - FlagData flagData = data.partialResolve(vector.with(FetchVector.Dimension.CLOUD, "gcp")); + FlagData flagData = data.partialResolve(vector.with(Dimension.CLOUD, "gcp")); assertEquals(flagData, new FlagData(data.id(), new FetchVector(), List.of())); assertTrue(flagData.isEmpty()); } diff --git a/integration/intellij/build.gradle.kts b/integration/intellij/build.gradle.kts index 0fd879d18d4..b437a1f5b28 100644 --- a/integration/intellij/build.gradle.kts +++ b/integration/intellij/build.gradle.kts @@ -10,7 +10,7 @@ plugins { } group="ai.vespa" -version="1.4.0" // Also update pom.xml version AND the version below if this is changed +version="1.5.0" // Also update pom.xml version AND the version below if this is changed defaultTasks("buildPlugin") @@ -43,7 +43,7 @@ sourceSets { // See https://github.com/JetBrains/gradle-intellij-plugin/ intellij { - version.set("2023.1") + version.set("2023.2") } tasks { @@ -55,11 +55,11 @@ tasks { } patchPluginXml { - version.set("1.4.0") // TODO: Use one version property - sinceBuild.set("231") + version.set("1.5.0") // Keep in sync with pom.xml TODO: Use one version property + sinceBuild.set("232") // Appears on the plugin page in preferences/plugins changeNotes.set(""" - Support for IntelliJ 2023 + Support for IntelliJ 2023.2 """) } diff --git a/integration/intellij/pom.xml b/integration/intellij/pom.xml index f8fef937536..b57bd8d379f 100644 --- a/integration/intellij/pom.xml +++ b/integration/intellij/pom.xml @@ -9,7 +9,7 @@ <relativePath>../parent/pom.xml</relativePath> </parent> <artifactId>vespa-intellij</artifactId> <!-- Not used - plugin is build by gradle --> - <version>1.4.0</version> <!-- See copy-zip below, which depends on this being the same as the v. in build.gradle --> + <version>1.5.0</version> <!-- See copy-zip below, which depends on this being the same as the v. in build.gradle.kts --> <description> Maven wrapper for the gradle build of this IntelliJ plugin. </description> diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainer.java index 620026c4ac6..b29bfd9af62 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainer.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainer.java @@ -8,7 +8,7 @@ import com.yahoo.config.provision.ClusterSpec; import com.yahoo.config.provision.Deployer; import com.yahoo.jdisc.Metric; import com.yahoo.vespa.flags.BooleanFlag; -import com.yahoo.vespa.flags.FetchVector; +import com.yahoo.vespa.flags.Dimension; import com.yahoo.vespa.flags.PermanentFlags; import com.yahoo.vespa.hosted.provision.Node; import com.yahoo.vespa.hosted.provision.NodeList; @@ -59,7 +59,7 @@ public class AutoscalingMaintainer extends NodeRepositoryMaintainer { int failures = 0; outer: for (var applicationNodes : activeNodesByApplication().entrySet()) { - boolean enabled = enabledFlag.with(FetchVector.Dimension.INSTANCE_ID, + boolean enabled = enabledFlag.with(Dimension.INSTANCE_ID, applicationNodes.getKey().serializedForm()).value(); if (!enabled) continue; for (var clusterNodes : nodesByCluster(applicationNodes.getValue()).entrySet()) { diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/PeriodicApplicationMaintainer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/PeriodicApplicationMaintainer.java index 3cec8483a45..bdff94e011d 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/PeriodicApplicationMaintainer.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/PeriodicApplicationMaintainer.java @@ -5,7 +5,7 @@ import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.Deployer; import com.yahoo.jdisc.Metric; import com.yahoo.vespa.flags.BooleanFlag; -import com.yahoo.vespa.flags.FetchVector; +import com.yahoo.vespa.flags.Dimension; import com.yahoo.vespa.flags.FlagSource; import com.yahoo.vespa.flags.PermanentFlags; import com.yahoo.vespa.hosted.provision.Node; @@ -66,7 +66,7 @@ public class PeriodicApplicationMaintainer extends ApplicationMaintainer { private boolean shouldMaintain(ApplicationId id) { BooleanFlag skipMaintenanceDeployment = PermanentFlags.SKIP_MAINTENANCE_DEPLOYMENT.bindTo(flagSource) - .with(FetchVector.Dimension.INSTANCE_ID, id.serializedForm()); + .with(Dimension.INSTANCE_ID, id.serializedForm()); return ! skipMaintenanceDeployment.value(); } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java index 1e9adea4e95..b2db5977109 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java @@ -19,7 +19,7 @@ import java.util.Map; import java.util.TreeMap; import static com.yahoo.config.provision.NodeResources.Architecture; -import static com.yahoo.vespa.flags.FetchVector.Dimension.INSTANCE_ID; +import static com.yahoo.vespa.flags.Dimension.INSTANCE_ID; import static java.util.Objects.requireNonNull; /** diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisioner.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisioner.java index e6f2dc0fbfe..239b962360b 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisioner.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisioner.java @@ -7,7 +7,6 @@ import com.yahoo.config.provision.ApplicationTransaction; import com.yahoo.config.provision.CloudAccount; import com.yahoo.config.provision.ClusterSpec; import com.yahoo.config.provision.HostName; -import com.yahoo.config.provision.NodeResources; import com.yahoo.config.provision.NodeType; import com.yahoo.config.provision.TenantName; import com.yahoo.config.provision.ZoneEndpoint; @@ -15,7 +14,7 @@ import com.yahoo.config.provision.exception.LoadBalancerServiceException; import com.yahoo.transaction.NestedTransaction; import com.yahoo.vespa.curator.Lock; import com.yahoo.vespa.flags.BooleanFlag; -import com.yahoo.vespa.flags.FetchVector; +import com.yahoo.vespa.flags.Dimension; import com.yahoo.vespa.flags.Flags; import com.yahoo.vespa.flags.IntFlag; import com.yahoo.vespa.flags.PermanentFlags; @@ -45,7 +44,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; -import static com.yahoo.vespa.applicationmodel.TenantId.HOSTED_VESPA; import static com.yahoo.vespa.hosted.provision.lb.LoadBalancerSpec.preProvisionOwner; import static com.yahoo.vespa.hosted.provision.lb.LoadBalancerSpec.preProvisionSpec; import static java.util.stream.Collectors.groupingBy; @@ -369,7 +367,7 @@ public class LoadBalancerProvisioner { LoadBalancer currentLoadBalancer, ZoneEndpoint zoneEndpoint, CloudAccount cloudAccount) { - boolean shouldDeactivateRouting = deactivateRouting.with(FetchVector.Dimension.INSTANCE_ID, + boolean shouldDeactivateRouting = deactivateRouting.with(Dimension.INSTANCE_ID, id.application().serializedForm()) .value(); Set<Real> reals = shouldDeactivateRouting ? Set.of() : realsOf(nodes, cloudAccount); @@ -427,7 +425,7 @@ public class LoadBalancerProvisioner { /** Find IP addresses reachable by the load balancer service */ private Set<String> reachableIpAddresses(Node node, CloudAccount cloudAccount) { Set<String> reachable = new LinkedHashSet<>(node.ipConfig().primary()); - boolean forceIpv6 = ipv6AwsTargetGroups.with(FetchVector.Dimension.CLOUD_ACCOUNT, cloudAccount.account()).value(); + boolean forceIpv6 = ipv6AwsTargetGroups.with(Dimension.CLOUD_ACCOUNT, cloudAccount.account()).value(); var protocol = forceIpv6 ? LoadBalancerService.Protocol.ipv6 : service.protocol(node.cloudAccount().isExclave(nodeRepository.zone())); // Remove addresses unreachable by the load balancer service diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java index dcf4e3160d4..8c52f389daf 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java @@ -9,7 +9,7 @@ import com.yahoo.config.provision.NodeResources; import com.yahoo.config.provision.NodeType; import com.yahoo.config.provision.SystemName; import com.yahoo.net.HostName; -import com.yahoo.vespa.flags.FetchVector; +import com.yahoo.vespa.flags.Dimension; import com.yahoo.vespa.flags.PermanentFlags; import com.yahoo.vespa.hosted.provision.Node; import com.yahoo.vespa.hosted.provision.NodeList; @@ -94,9 +94,9 @@ class NodeAllocation { this.nextIndex = nextIndex; this.nodeRepository = nodeRepository; this.requiredHostFlavor = Optional.of(PermanentFlags.HOST_FLAVOR.bindTo(nodeRepository.flagSource()) - .with(FetchVector.Dimension.INSTANCE_ID, application.serializedForm()) - .with(FetchVector.Dimension.CLUSTER_TYPE, cluster.type().name()) - .with(FetchVector.Dimension.CLUSTER_ID, cluster.id().value()) + .with(Dimension.INSTANCE_ID, application.serializedForm()) + .with(Dimension.CLUSTER_TYPE, cluster.type().name()) + .with(Dimension.CLUSTER_ID, cluster.id().value()) .value()) .filter(s -> !s.isBlank()); } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodesResponse.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodesResponse.java index dd6b0b5a6df..5c379fb1608 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodesResponse.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodesResponse.java @@ -13,7 +13,7 @@ import com.yahoo.config.provision.serialization.NetworkPortsSerializer; import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.restapi.SlimeJsonResponse; import com.yahoo.slime.Cursor; -import com.yahoo.vespa.flags.FetchVector; +import com.yahoo.vespa.flags.Dimension; import com.yahoo.vespa.flags.PermanentFlags; import com.yahoo.vespa.flags.StringFlag; import com.yahoo.vespa.hosted.provision.Node; @@ -199,13 +199,13 @@ class NodesResponse extends SlimeJsonResponse { private Version resolveVersionFlag(StringFlag flag, Node node, Allocation allocation) { String value = flag - .with(FetchVector.Dimension.HOSTNAME, node.hostname()) - .with(FetchVector.Dimension.NODE_TYPE, node.type().name()) - .with(FetchVector.Dimension.TENANT_ID, allocation.owner().tenant().value()) - .with(FetchVector.Dimension.INSTANCE_ID, allocation.owner().serializedForm()) - .with(FetchVector.Dimension.CLUSTER_TYPE, allocation.membership().cluster().type().name()) - .with(FetchVector.Dimension.CLUSTER_ID, allocation.membership().cluster().id().value()) - .with(FetchVector.Dimension.VESPA_VERSION, allocation.membership().cluster().vespaVersion().toFullString()) + .with(Dimension.HOSTNAME, node.hostname()) + .with(Dimension.NODE_TYPE, node.type().name()) + .with(Dimension.TENANT_ID, allocation.owner().tenant().value()) + .with(Dimension.INSTANCE_ID, allocation.owner().serializedForm()) + .with(Dimension.CLUSTER_TYPE, allocation.membership().cluster().type().name()) + .with(Dimension.CLUSTER_ID, allocation.membership().cluster().id().value()) + .with(Dimension.VESPA_VERSION, allocation.membership().cluster().vespaVersion().toFullString()) .value(); return value.isEmpty() ? diff --git a/parent/pom.xml b/parent/pom.xml index d4a2036eb5f..7642b87ac7b 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -317,7 +317,7 @@ --> <groupId>org.openrewrite.maven</groupId> <artifactId>rewrite-maven-plugin</artifactId> - <version>5.14.0</version> + <version>5.14.1</version> <configuration> <activeRecipes> <recipe>org.openrewrite.java.testing.junit5.JUnit5BestPractices</recipe> diff --git a/searchlib/src/tests/queryeval/blueprint/intermediate_blueprints_test.cpp b/searchlib/src/tests/queryeval/blueprint/intermediate_blueprints_test.cpp index dd88684dfee..38e7e27163d 100644 --- a/searchlib/src/tests/queryeval/blueprint/intermediate_blueprints_test.cpp +++ b/searchlib/src/tests/queryeval/blueprint/intermediate_blueprints_test.cpp @@ -627,71 +627,106 @@ TEST("and with one empty child is optimized away") { EXPECT_EQUAL(expect_up->asString(), top->asString()); } +struct make { + make(make &&) = delete; + make &operator=(make &&) = delete; + static constexpr uint32_t invalid_source = -1; + uint32_t source_tag = invalid_source; + std::unique_ptr<IntermediateBlueprint> making; + make(std::unique_ptr<IntermediateBlueprint> making_in) : making(std::move(making_in)) {} + operator std::unique_ptr<Blueprint>() && noexcept { return std::move(making); } + make &&source(uint32_t source_id) && { + source_tag = source_id; + return std::move(*this); + } + make &&add(std::unique_ptr<Blueprint> child) && { + if (source_tag != invalid_source) { + child->setSourceId(source_tag); + source_tag = invalid_source; + } + making->addChild(std::move(child)); + return std::move(*this); + } + make &&leaf(uint32_t estimate) && { + return std::move(*this).add(ap(MyLeafSpec(estimate).create())); + } + make &&leafs(std::initializer_list<uint32_t> estimates) && { + for (uint32_t estimate: estimates) { + std::move(*this).leaf(estimate); + } + return std::move(*this); + } + static make OR() { return make(std::make_unique<OrBlueprint>()); } + static make AND() { return make(std::make_unique<AndBlueprint>()); } + static make RANK() { return make(std::make_unique<RankBlueprint>()); } + static make ANDNOT() { return make(std::make_unique<AndNotBlueprint>()); } + static make SB(ISourceSelector &selector) { return make(std::make_unique<SourceBlenderBlueprint>(selector)); } +}; + TEST("AND AND collapsing") { - auto top = std::make_unique<AndBlueprint>(); - addLeafs(*top, {1,3,5}); - auto sub_and = std::make_unique<AndBlueprint>(); - addLeafs(*sub_and, {2,4}); - top->addChild(std::move(sub_and)); - auto expect = std::make_unique<AndBlueprint>(); - addLeafs(*expect, {1,2,3,4,5}); + Blueprint::UP top = make::AND().leafs({1,3,5}).add(make::AND().leafs({2,4})); + Blueprint::UP expect = make::AND().leafs({1,2,3,4,5}); optimize_and_compare(std::move(top), std::move(expect)); } TEST("OR OR collapsing") { - auto top = std::make_unique<OrBlueprint>(); - addLeafs(*top, {1,3,5}); - auto sub_and = std::make_unique<OrBlueprint>(); - addLeafs(*sub_and, {2,4}); - top->addChild(std::move(sub_and)); - auto expect = std::make_unique<OrBlueprint>(); - addLeafs(*expect, {5,4,3,2,1}); + Blueprint::UP top = make::OR().leafs({1,3,5}).add(make::OR().leafs({2,4})); + Blueprint::UP expect = make::OR().leafs({5,4,3,2,1}); optimize_and_compare(std::move(top), std::move(expect)); } TEST("AND_NOT AND_NOT collapsing") { - auto top = std::make_unique<AndNotBlueprint>(); - auto sub_and_not = std::make_unique<AndNotBlueprint>(); - addLeafs(*sub_and_not, {1,3,5}); - top->addChild(std::move(sub_and_not)); - addLeafs(*top, {2,4}); - auto expect = std::make_unique<AndNotBlueprint>(); - addLeafs(*expect, {1,5,4,3,2}); + Blueprint::UP top = make::ANDNOT().add(make::ANDNOT().leafs({1,3,5})).leafs({2,4}); + Blueprint::UP expect = make::ANDNOT().leafs({1,5,4,3,2}); optimize_and_compare(std::move(top), std::move(expect)); } TEST("AND_NOT AND AND_NOT collapsing") { - auto top = std::make_unique<AndNotBlueprint>(); - auto sub_and = std::make_unique<AndBlueprint>(); - auto sub_and_not = std::make_unique<AndNotBlueprint>(); - addLeafs(*sub_and_not, {1,5,6}); - sub_and->addChild(std::move(sub_and_not)); - addLeafs(*sub_and, {3,2}); - sub_and_not = std::make_unique<AndNotBlueprint>(); - addLeafs(*sub_and_not, {4,8,9}); - sub_and->addChild(std::move(sub_and_not)); - top->addChild(std::move(sub_and)); - addLeafs(*top, {7}); - //------------------------------------------------------------------------- - auto expect = std::make_unique<AndNotBlueprint>(); - auto sub_expect = std::make_unique<AndBlueprint>(); - addLeafs(*sub_expect, {1,2,3,4}); - expect->addChild(std::move(sub_expect)); - addLeafs(*expect, {9,8,7,6,5}); + Blueprint::UP top = make::ANDNOT() + .add(make::AND() + .add(make::ANDNOT().leafs({1,5,6})) + .leafs({3,2}) + .add(make::ANDNOT().leafs({4,8,9}))) + .leaf(7); + Blueprint::UP expect = make::ANDNOT() + .add(make::AND().leafs({1,2,3,4})) + .leafs({9,8,7,6,5}); + optimize_and_compare(std::move(top), std::move(expect)); +} + +TEST("AND_NOT AND AND_NOT collapsing into full source blender optimization") { + InvalidSelector sel; + Blueprint::UP top = + make::ANDNOT() + .add(make::AND() + .add(make::ANDNOT() + .add(make::SB(sel) + .source(1).leaf(1) + .source(2).leaf(2)) + .leaf(5)) + .add(make::SB(sel) + .source(1).leaf(3) + .source(2).leaf(4))) + .leaf(6); + Blueprint::UP expect = + make::ANDNOT() + .add(make::SB(sel) + .source(1).add(make::AND() + .source(1).leaf(1) + .source(1).leaf(3)) + .source(2).add(make::AND() + .source(2).leaf(2) + .source(2).leaf(4))) + .leafs({6,5}); optimize_and_compare(std::move(top), std::move(expect)); } TEST("test single child optimization") { InvalidSelector selector; //------------------------------------------------------------------------- - Blueprint::UP top = ap((new AndNotBlueprint())-> - addChild(ap((new AndBlueprint())-> - addChild(ap((new RankBlueprint())-> - addChild(ap((new OrBlueprint())-> - addChild(ap((new SourceBlenderBlueprint(selector))-> - addChild(addLeafs(std::make_unique<RankBlueprint>(), {42}))))))))))); + Blueprint::UP top = make::ANDNOT().add(make::AND().add(make::RANK().add(make::OR().add(make::SB(selector).source(2).add(make::RANK().leaf(42)))))); //------------------------------------------------------------------------- - Blueprint::UP expect = addLeafs(std::make_unique<SourceBlenderBlueprint>(selector), {42}); + Blueprint::UP expect = make::SB(selector).source(2).leaf(42); //------------------------------------------------------------------------- optimize_and_compare(std::move(top), std::move(expect)); } |