diff --git a/api/api.gen.go b/api/api.gen.go index 89b4b85cc..89b498447 100644 --- a/api/api.gen.go +++ b/api/api.gen.go @@ -357,6 +357,9 @@ type EntitlementMetered struct { // IssueAfterReset You can issue usage automatically after reset. This usage is not rolled over. IssueAfterReset *float64 `json:"issueAfterReset,omitempty"` + // IssueAfterResetPriority Defines the grant priority for the default grant. If provided, issueAfterReset must have a value. + IssueAfterResetPriority *int `json:"issueAfterResetPriority,omitempty"` + // LastReset The last time the meter was reset. LastReset time.Time `json:"lastReset"` @@ -405,6 +408,9 @@ type EntitlementMeteredCreateInputs struct { // IssueAfterReset You can issue usage automatically after reset. This usage is not rolled over. IssueAfterReset *float64 `json:"issueAfterReset,omitempty"` + // IssueAfterResetPriority Defines the grant priority for the default grant. If provided, issueAfterReset must have a value. + IssueAfterResetPriority *int `json:"issueAfterResetPriority,omitempty"` + // Metadata Additional metadata for the feature. Metadata *map[string]string `json:"metadata,omitempty"` Type EntitlementMeteredCreateInputsType `json:"type"` @@ -3272,125 +3278,125 @@ var swaggerSpec = []string{ "64S5FB1jIYG5+gVB9TkXobVHhKJtewmsS1oqkWYOVcu3umZ0+XlMgEfVHTL8DIchEUKx4Ei1mYBT3AAr", "nsRZZsgATd4nn1NxyofScUUt+tVXvBOFbf2dUk0KBhJ16VsmZeclV4QhWg0doYqTjnEqpLWMlF32WwEV", "5wxcW20owQLQUtu6GWjqJ9vDqCL1kIiUgFBRQ8Q/8xTmgIbWUzOVfIKB2cczI71ogkZnYypMKyrA78WR", - "qzQQDaSLsn3XGkQL9t1J9hJRESnXZ93xPNukcw9SSSUtGxebnSGvMed+h259HO+rRfShLKJm9jmxapkL", - "7CWZWWMdeApkoBfmzUM61ntKKkfDgbyAcJdaFp8V82yxwk1zv7eCzyHJeCB8sCtVz1W4lUbceMcnZKpY", - "NQN1yJJ+yNmQjlIttfruUt3AT5XgazLFiQAVR7f0xFSWz8TtRXBJZpsXwQ66CMDWtHkR3M170re3gXne", - "KlwG5reGL+9mOQsp8r0Cq/omZNR9PzocM2Kt+Hlv97NG+0GcDTF7a4x6AJuoUEmn2QYtNJOPseiD7FYF", - "8MOYABN1me0YCyvrGV7mhKWWwh9r5nYkGiVo1PramY/NNme1ranz9Gvq5YdMKKmwwIoCUNsrev25pyDf", - "H68icGV9WOf5hZXUr5inEXQU6NQYzzXBATWeaufTgq3P2gkLQZFtmSYDro6xjnbeCTZ7W75QSfD03w43", - "u0MckfZm+IK0n0XfhO3nvW+32+F2L9z65tutzWhLsQTB0wR8/wRJrmhI2hAi0grElIRXJBF6CZudbuC6", - "+JdiQeikrKFt7sC/nW5385ccwmnCJ1Pp8Qacaxb1eVbCS5dCKZriWcxx1JkTTVqDOJ+JVEFiPJX9zlIm", - "8AScoCytwtOqDipER6mQCEego0kOUWi97rNvbBSagtJwatcLGryfCzy78hWsOG8IG8kx2HFYGoPdrJbR", - "KKjcSKSC2lTy4oNm2rgEi9ELUCynU/XfWhIOGi2cH3ayyGAbkm8RlqrQaKh7wfyw4zdSMRttzcbMUNcY", - "T6eEkSJ5lc+Ki5925i/ZADr3jHlD4vRHS2cuIxEFRpLZ4A3YqShxRnOCFwFUFzG9B38NLLmYu8nKMTCl", - "YdQWlYVv04RHaUgS9CST0sEbU2/P045fLgfesgBizXoquKMTIiSeTBUY18b+7Dp4ZtvqO69bW1svOrW2", - "pxJn89qfljwhfk5TxLnlNxqhCdHmPCMSaI9WbcXPV1lcg+G9i4RAQLo5NkUKbVkB0VJJ5X5sBTftEW+b", - "H/Wh1hem86Wt3xd0UhWFoWBE5TgddEI+2QgVhUNHsSGiy/aIb1z1NuAHgLTygll93M0N6ibsFcQZx/2h", - "LLzXvlOTylDQGMX0kqDNHppwJseibHvv+UzsUZq/1TaZyLbXc8FEZh5zeXz/9vwkaAV7/Z+DVvBhf/91", - "0AqO3h6ffR+0gp/3+yfO5tRsdAZSy+DAJ+6YXC1Fbaz00p+EY3rl95U4LMlyAtnWLUSN54frJOE8xfPE", - "NV4+iMuK5/6fr2oabCylSVetVRUVul9AUPYHT5C5ZxCHt1Q47hhZ/lh8ndtBu+/O29/zNBEtdAZyTgv1", - "3x2iXRzHooWIDGv0cN+qPL7pnxPGIoVd1pl8jI2nmohIp06wcQtUomHCJ2jG0wQ5clWZtOZmEvrCLnmg", - "jplMGjp9ibgHHG+nORQkT/ZiEsCIDjoXZJjG1oKvW4mQT2H7BwmHGGx474WX/AztCQ4vyxyxnNrlrm55", - "/gw9ZxkAmZ+dS4pFTzt4U42IdloSlpcMZhkvORwiY+LRL61enTPETLEkowKXyURTyCeITPPRiY6x93q/", - "OUkNCtvtpAU4NAdj4UWtzaQwmY9zgwvByzRhe/yambjDUzLKYiRKp1voTwU/BDRIE4Yifs2cKMQL1kcj", - "ekVY1iUzmokiRrH1h2QI505jbrheTTjjPouWDmYkLHqQUMZHG2MJuDV+LCLDWR0/aPCsVG+sGyQEXwIZ", - "KPkTK/VIu8/p/a1f6o52ZDnc20EG0jJnmPNYoTBzV4uInNBLiMj26a+KCni28hoXlYpoOOK1fkKWKTxS", - "qnMu9UEvmNuAmw5mmse7T6VZyqN5ks+rDJoTEvIkCuqXYDIkzbFPvr0iiX7J1f4v7B8Shaq1ViSNf2YR", - "p73tLx29XLhdMm74GaKWK7ivmOlr8wsWA1S9buPLPTEuhZ+V/H19GFgq5V9n3gWfh/aUYv7fHO6hJ+eM", - "KgUZztG5HvcNuaEhHyV4OjZeAKc8kfDekNmdkqcljL76ZvuXb7e3+wcf+q+/39/sHf/c3f3xxYHS56ZY", - "SpKoKf/fr932i/7L3b39g1ff//D66PjdjyenZ+8//PTzLx9ve9/c/d2D/9v6lU3wjTVTfLNVtlq4s+L2", - "7932i4//evLvnU/ZH0//6Znuo4cADtmICEmiVWznfcWSdHdj+gAxj1sBFrJjaFUZEi+UzMDETrmMQX0J", - "C3r05Szo+cp1rotKShmd70ubTsqyVoaXuS+rtm9lKpembIYSYgw9SwYxQC+fAAuuT77Tq5cJamjx+U6b", - "ryE/mEBjfg3++FiGWivIM6hp+1KJUuxn80h8fhRUSPFQZ2HRXEv1VuOcFfallSUPdGjt751CykD1gw0b", - "FMChyucSnhLM0Zjp9lYncPKx7QRHh8fnZ/vV3S2sZf4eA5b7Tvuy+FPFv/O3Zd1ZptSqIoPODbYWWkEd", - "dN7WvvaAGVTyfDebGTkL+1InGebDVHasTpE+xhMSwTPeOwxpUpUqBLkjFJDkRinENjbMTT4ptEUit5Ar", - "/tRBr8lMZIkqzC2laDfkTFAhEWfxDOF4OsYshfxx8DVlEUlEyJXmOsZqRqXD+1XwObRYzQwRrZgvt+G9", - "tvCpXMy9vytZEmpB0kb++yLxM9yelaNfXruH0sqEpp0YMvIq3p7/EPp9z0Yxdy7YmdvIdOYJOj0/aqH+", - "+1ctdHR43AIUHfV/Qg5rEZoHM5MLFLIOwjo0IzZGFPC1MFbBLKTrgCfo/Pjwx/P9T7tvz4/P3GFbRbA1", - "RHnyFj1FB6khKn1zBFgUKhjpiHGPHcfhqpVtuC7k6lwi22XB70unhna5scvlCrMseEuBQys6+k5s+pjC", - "p4TpeDSe//fG9HK0oYcDgCsXgD9kz8WxYcFKHaseffM+oS9Q2KCgFbh7HbSC/vtXQUvdXup/+z8VH751", - "z+KO1COjX0DuuvHyY0qS2QkR4H/sw0sC3xyPGQS5QTs+b45fb33CQUkQLUt5dQLjlXa+2uxZKgIDUF2a", - "WkNo2jTif0JRkjvkga59YpF84QTzxRIrg+e5lB89RhoZOhxS4dfVvM8Wr7frCv2UfG25idfE6WBna4X4", - "DDWeqzzh19Yk0uwsPWaCaVVsLAtlznkBnw3XVyNYO4ny67w6zqq+HBrx2pdpjlfGQmH+yjqH+h7Gc1ub", - "g/h1U7S1Az9EBJFeXXEqdzFL3ObZ4Vjr7VXnHdHX4Vba+uh5gxl66wzo0YxZW+fa1/4yeTD/NRY2KrWD", - "Dof2mXUQk7VGvUteCx3J6gB8EdhKFGJKKkjuZYvveCJxDPqxb4+UpqJUEwSBuLE2O5TtFXHMr8GxQD+c", - "CvDgdjWUj63ABIn2Zf3adDaRyKmokmUXqTuGJpH0HM2u1sylVxzwySe9tE+Hfba39W764UOv3/uQPJ+8", - "+O/wd/J9/Oqn5zeT3Z+uX3Vm2789O233P/x2kH7z23+H+OD37u8//vZs//fe8xPBZu+vfxgOf9r+7ebo", - "insMIVUk3dY8hbcQHWbJ5UFFLObQ18WfsuBfM7K7J1X011eGmFB2qD9ulsSFVqC1W/NZsde7wkbePlT+", - "lowSbhs4kheS0KzGuBcCRKNyVaJ7GRPyW7BhTvuMXv2JaS8JU9ol0EpWjEEpvmqvKC8e2Ici+WXtrbW+", - "e4orrZLito9MN7QHCRqFyayKnpwc7KJvn3e/fdq5YI7jS35CS/lciwkm0QTPwH6gfQvKGpXNhzs3tev6", - "kv3/YZLXfs3m+jWb6x85m6tXUD6FXpY9rVVQLsduVtCZNXDdiVk1dq8keEASKQ9RMISTAZWJ2n+TaUpy", - "iNs3OnB5NlaOC58nHiuqTK5wvGTE6j5LJ1VHcDtWy67Gd2fMiRB/lKg0RX+mNo+XHBOGTIoBeLNh/BrJ", - "JGWh618/5mnyxfehAfphgAqm3sCrBzg+tq2Eq3EiCqb6zAU7R50udgfxQVEaUzYCD8C9/s87CP7ZvyLJ", - "DEV4dsE+7O+/3nF+vCbk8oKBT/pO/iu4sl+wn/f7J27jGcFJwb99Gcf2VlBxst7xJNIw7rZuApSE6Md7", - "/QwiiP0KOZYKeRymfGoyqJhrx6TocYtvgUxzrSQXVpN1oyDGN0kraAF0U/50Hi6FoynQuSJ8pncHHacx", - "+A6rk2Z/fDigqZdr4wgEc3+B1/Um5Eyn0T12FZLgmCE6aM9hRRm1WFzaVg8YEFEJBcpJ1l2ojxc55TaX", - "cfBx00rg2npmqdBvjJ4iCVnCDssDcytur4yVQsu5xtxWEFExjbFN9LxrNEV0rL17FhtBIGyhHM3mxBCM", - "04GYcp3Jb7O39Wz7Gy0MJ3RK7GzwMUzFp1yurqoj1eVXVfJeI/pYaNb14W9Vg8TiAFZ3A9xZynvRMAR1", - "XZYEE4/S2IqwOHBET+RQtJ82Flv6K8RTAtOlo4V48wQc+M79vLqWzvOsrW0k6O/EfSk2r4UtN6St8CCc", - "NWjwJvzBLVe5RjVBj0uiYh0nP7+/Nm0blXBKE9WYzR2wJhjD50rc3DG7JjTE83pp17Pqot/mBjKBEn6t", - "hS/dQeTW+kRfh07QX6PFeCtr+WrvluhWnRYl5lI5gwQMej8gwnqX80tK+qmilFtfLgeIWbsmA4SnUxRC", - "a1tnM/vLVNr89EloNx2nLtKUviaAWRjMeQuwUw4ITkhyYJkmn+Lf4LnJB4r3rcDWIAX7EQyWTz+WcppN", - "vvK0CgONp1q8xP9ey8BTPKu6MkX06pS2jQSVBycvgOLOVHZKGI73eOhREfZ4mKozYJ1J0iQ2vcXORs4a", - "OpRvRGoA0POG3PekQNiR46QKCGMY4kS0x3uWJdq4DBs3rLyjQi88MQg046nOxD0iQhrf1ZZ+GjevtTCm", - "dtHSqkcmYIrOBWu32xfsn2+nJDFeW1nS1P/73/9BTwC6p0q81FxaqT7aQy5LzEqZAxlsf+efcEBjGhJT", - "3c+Qe3+KwzFBPXB2zhFoCvFi+AqleE1XsfHmcHf/+HS/3et0O2M5iR2LWlDAR9AKCt7UnS4EjEwJw1Ma", - "7ARbnW5nS3vLj2F3N/CUblxtbkRkkI42JkQmVG/7iHiNE5pBQWtkWuvwa6hHnFW8LjrUCSSoYncTyiJG", - "R2OJzs92i9sJA+3yVOnxT8RTk8aYWM0ZYYkmtNA5gHXp/QIR4BWRewouM1pQqrXb63ZLFRYluZEb0xhT", - "eL3wVfP9G/p+/807lJH1J7Oc47qFXrC/obOf3+1Xu4R6bRes/EW/hN3aWvkXTsq1i+AOgWDT6S7ZrwV+", - "/t9dBEpmgWGA2Dz1iEvHe0DyjW3pna3d1Y6irWfdzbrbJ0P/xrwqoACDyV65eJy62pm6EDSYjDUpGJfh", - "SUYMEuvnX6CR4KPqYInfMa7V0z4YiNyWnQoFqib77ljqoCVYv4rW5mjLm2w4pe/rQubLrU31+WoKt7dJ", - "RBIdr0ziqK7mvGpUquKfl+N21VoriS5SdTPa+rjw/FWy9xROYSPBxi1qVpVnqmWLjZGvuI2PlYorFOdQ", - "sUtm6Mn+jZJv4V6On5Zo+2oxVZe5tbr8ICAZjDEJZlbY9JD71eqEfpDwSWM6P+MeGs/5sIEcUhqoO6qG", - "3iGlrZ/aIYquGFOXPXHpv+bkB783tbvunivFY/0BE5xB2N2Sa1W3oZP6IZXuYl9s9qLN6Pm37e4LHLWf", - "DcKwjbe/jdrbg63t7d6zF1sk6j30Ynt1i23qKFsMBFyGqekjoPRGkM9GlI0Mc+suZkovcWReUT2s7fGy", - "xxLrcjmk/uHjXSuYcuHLuwNdRZ7GjCdoAJFwLjKVfqHDNeakFvNxRz18xh/N0/BLHs3mMAYntdO/qkyi", - "QRziXatuvDas7V/zWc+fPaXin5/PNGUzjdlLHlboOR+Zzm20OUPlqOSP4x4cxzcH4qGUNp1gcPSoaSbM", - "4HWjTIrZ6contTabqD61ufXWuBGW7vFnVc5xmkLu02Eax7OMA/2ZWe2ha1fx8VhH4DQ5exaInLZVnVx5", - "YEf5g6tQcIit7tTorTB/WKheWJDWN0sPlyOxBjSqO/RNez+I5sGx7L36efQ3mzpvCTEnX/SjFkyGOQE3", - "09nqxBTtLSTKmeKLR0Y3sthsKm0sJ2F4E/v57wsnw5wm904DRru5bkh90B3Y7GXWTeTRMO3tJmMcc3mo", - "hDVFNp+HmPV22x1dxQJhT8LGbVbJ4U6TeUykN6Wr+t3JnziYoUsy85G9bpqT/XJXRV5YwsPsPNe+pZ3M", - "W2dNO/9MT7Zw5w94yj7LnpsdWHbPW/77/hWR7lbSqMZ4/yDb2P2cTAUyyvx5ycLZyFX4gE4/Nl8sxHFc", - "SFNWFQx11cc/uliYC373kA4XLMJIf/owr+FwLGuQ16XLl5DszMY/brluZOlvRfrfuDVJ5ebege85jdAT", - "/fVplpkb9W3dTcz0+/Mgu40QHSIKlVDYP5TWDSmYiJfXqsH15ix7imw+vGb3JcwBtVkAHF3z+xFJXPdl", - "sM+6Lxb33+VsGNNQfsZ725DLKjRqSWEej9Zt/K+fR7r/Gh9DvkzKsQbRu2tJSrZU9oxleKndpEfNSyeW", - "WiydGvKpV4b/2V/gcPNPU2PY4/7UsuHJONf/nIIcTo68IY2JGuyCGe3H5Nqo17xtzqGH0LvN3vs1bZP0", - "e9169hfP+fe5DmDrvpuw+9WQ0OzE/9///g8yx2liTkvl2Fduoo1b+H+bp3auzLSQN1yw7ILUx2YwQ4d7", - "UJ4hTkf19gV7uJeTlQqAN5SYNMBF+8L9ZJRHTAxmM2qJYY45wbN9PovCA21c9ysDXSMD1TTvmk4eodlj", - "dY6lbQm1EvWPjovyMCvnUyFmaLYWcm49nG9Wk6ZufrSlupzRCfmFs+bddAEYG2+3XC9TQ6Zxr6z9vZnF", - "XzYL4hJcxE04CUEr5EZuhOKqzotbz/gJMnO1zB+ERS2DsBbgt6Xw2QJcXTDfslqlHzfhR4vqT5stZ3ta", - "4BLT2uxVhtosDqVR01s8VK9bGarnG2qrOFSvMJR2Y2k9a+IJDhmpdcblP7Fjg8N+V+PuhoYWmExsKxOn", - "myWCrTGgnNpBv4jo4rPDlFhKTl/zM3g1tVZY/KyJ1B7QWpGBuoBcdDhWkWpWkQdKkWsddDamAhEWTTll", - "EA4+TQcxDeMZIjdTriuoS571EzWyhI42q5EoVshmDk8gEDeavYDk5crKNomWl03PLxn2VxNcPrMI8vX6", - "/Xr9frbr14QUA6+phL3++lGRvD/q99ePirzL17cJfS3f4rq3ly1bN98aJtzAkgQ3gjesuPbl2lmNWMRz", - "88CWwtB5fEuWBEVdAb3tzvLxLr3tUhWwzxjt0ujNw83/uoQsUdyLr2bZBpY4QF0Bb75jNN9BURca8mfk", - "9b2YuLu77LvJshl+/ZpxY6WzQIj+Z5hC9P1SrzHru5wXgPn4HioeylexlOSh8X2wYap0Yf26sOIL5AU7", - "zIYRNVeEY7rWpOkPILLDlG6OlQ4LkFs+JMJx7AuJcr+XWWmesP4OCtZlbWE180crnhDo4A640FxdnbE2", - "Yf+8RRgF3GLdhaCGSdwV2EQxMY0vqVqDRc/LunyfpSys3F5lCpDpESpZJm6KsSyjdwvmNRPatN75MYk6", - "qwXQvCsspDDe1/t68X3tkMXCW9thdgttVU3l3sxcUyPpOvarhxcTcwv/quamR3iTZVKZx9yUYfcebjIX", - "7HwqSCKFw0GQjTThiUmiKJzr6VDnYbZMIuIEHA3JDRWyhajMuIONrKh0gaai0HaKE0khdajxdc3z7mTJ", - "Z3W2UR+p6SXY/V/d+WbdZOZWjJEcpQDm+mXBdYNtmhp4v/LiZqdUE2EmjXiPqYcHb9jEPYfR2+Q1ma3N", - "s8USXiZhzg2dyQ/Pcg8NReAberdYAiv6t/wZPIEfv5fNXPpsrSwOvCKyMcW9IvLhyG19anTGMes55J88", - "zkeRjbOxq/O0JRJrKTXDbV3SbuYLmvfKuVWmrccfWPM101XTqOlS5YTFRKW7ubheC6tav1O4A2KTgGwX", - "CV8oKLtAwFUonc+PMDj7vqE+jzu4mxTofemgoWb8f+PW+Uu1MFGz0DCzwtW6/Cqd0KZNhuqnWRmmSmmU", - "itjhrOS9KUr50HdE7Vo98aTvwJWDD03tA47CMQkvdX3RHZRlg1dC2MnBLtra2nqBdLL4YikExq9NTmjP", - "S6DJJ+97oL9PQceHlMQq29aAuZmirH8azeJBvJmbnaXPxgoaZYMoXuS1eQR083Ve4Eue9Ya6sHvd/VXy", - "SaxyzcwJAmlED0Xu/xiIYTn+iOP47bAWUr9yUH6mirGQJ0SQmtI7UFsHLhidd/0aC51++yFL6JRepj4u", - "kAj/Apk1voQQdrdkUg6tQLFFIlcpD/aKKTvuffaW1+QfZ6qPr4k71pe4w0PBa7M1mOQczc6I7rRaGo71", - "3EoPapSAhbmFLmtkd42yL2+SMDRfBVInMfmaLm45i8LKCUhWvMbGedmlRhYEWx1qniVBJ521JZhwohTw", - "ME4FvSIIw3A0QeDVDlVlyE3lI2GRSV0LMpap7WVqdosJjmOSIDnGOgeFU/oLBqSiOOGAy7EaUiyWc20V", - "qi9x5ZaeTAA/1rYBpQTUadeVeZzOS9g5Lpi0GNViKjxDiWpBWkWEaYwTKrMy0imLSBLPKBu5GT18lzoE", - "OK7fXtKqKoLRetFjzECmhi9U6h0ThkbrR5HknwNBp+o8GNhg/eacSI4gRlbXHjbneTDroF3M1MrVERvz", - "RNojpmOqnAXXL+zaLZA3J3RpfnG+FQOYylFDD2lhq6nYt0AZK1evQ4dDyybVXrn+g5r23B2iQm9bXiTY", - "LXl4wb6a7hqb7hZfYp/xBk6sgcEvI4P9IS8CbShJGxzUZWfuUcTIta3ViLTeWKi+rW7hhMcxiRC/8idk", - "gpmc1Z6bnBp/HBG7aL0hwyEJJb0idaWTgSliia7HNBzb0skK2fiSCKS7t8rl27N8/aplmHFMkw5rmJpE", - "02euJx7Y1tUBXv0aWcsdoTArMWX9mqL3p2OexpGDCd1cgwUUZ4rd64L4xlNRMfe6JmrRehDr2Kizps9v", - "D5ugEeRsIuyXxkYl57rXY3sF/2qXWxtT3le2WsdWNWtayfxWCmbMAhf94YxuyVQTyUiSK38AYMxDiIIu", - "lIfc7H3b6Xa6nc2d58+fP/dI21DuZU5VTv1dzWwW6JFGIbBckW9sT7iucKFOsuLUWW0hQ/imFuAF+/UN", - "wQlDE56Qj09qK4JujIhUY7WB45NoA0bZUNz8ipLrp3AwjBxmykt4heYqmKCjUzbSRT5Blsq4zz3gM+zd", - "C6CJ/G8IoEk0WIjnbwzWhDMi6e9kI8JiPOA4iUzwUjsiVyRWN0Z7lNKIFAA0YQANAXT8+ldElh2hAETm", - "NdYQjILP0vIIKogpfrqac6qrMO5lBG/TLogOOhdkmMbFYltAd1IflY47ny45effx7v8HAAD//6LrGqsx", - "+QAA", + "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", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/api/client/go/client.gen.go b/api/client/go/client.gen.go index f7695d09b..59c83631e 100644 --- a/api/client/go/client.gen.go +++ b/api/client/go/client.gen.go @@ -357,6 +357,9 @@ type EntitlementMetered struct { // IssueAfterReset You can issue usage automatically after reset. This usage is not rolled over. IssueAfterReset *float64 `json:"issueAfterReset,omitempty"` + // IssueAfterResetPriority Defines the grant priority for the default grant. If provided, issueAfterReset must have a value. + IssueAfterResetPriority *int `json:"issueAfterResetPriority,omitempty"` + // LastReset The last time the meter was reset. LastReset time.Time `json:"lastReset"` @@ -405,6 +408,9 @@ type EntitlementMeteredCreateInputs struct { // IssueAfterReset You can issue usage automatically after reset. This usage is not rolled over. IssueAfterReset *float64 `json:"issueAfterReset,omitempty"` + // IssueAfterResetPriority Defines the grant priority for the default grant. If provided, issueAfterReset must have a value. + IssueAfterResetPriority *int `json:"issueAfterResetPriority,omitempty"` + // Metadata Additional metadata for the feature. Metadata *map[string]string `json:"metadata,omitempty"` Type EntitlementMeteredCreateInputsType `json:"type"` @@ -6951,125 +6957,125 @@ var swaggerSpec = []string{ "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", - "+QAA", + "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", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/api/client/node/schemas/openapi.ts b/api/client/node/schemas/openapi.ts index 0b6d0cb50..08c97038d 100644 --- a/api/client/node/schemas/openapi.ts +++ b/api/client/node/schemas/openapi.ts @@ -578,6 +578,13 @@ export interface components { * @description You can issue usage automatically after reset. This usage is not rolled over. */ issueAfterReset?: number + /** + * @description Defines the grant priority for the default grant. If provided, issueAfterReset must have a value. + * + * @default 1 + * @example 1 + */ + issueAfterResetPriority?: number } EntitlementCreateInputs: | components['schemas']['EntitlementMeteredCreateInputs'] diff --git a/api/client/web/src/client/openapi.ts b/api/client/web/src/client/openapi.ts index 0b6d0cb50..08c97038d 100644 --- a/api/client/web/src/client/openapi.ts +++ b/api/client/web/src/client/openapi.ts @@ -578,6 +578,13 @@ export interface components { * @description You can issue usage automatically after reset. This usage is not rolled over. */ issueAfterReset?: number + /** + * @description Defines the grant priority for the default grant. If provided, issueAfterReset must have a value. + * + * @default 1 + * @example 1 + */ + issueAfterResetPriority?: number } EntitlementCreateInputs: | components['schemas']['EntitlementMeteredCreateInputs'] diff --git a/api/openapi.yaml b/api/openapi.yaml index fc07dd3d8..c7ffbf19c 100644 --- a/api/openapi.yaml +++ b/api/openapi.yaml @@ -1560,12 +1560,19 @@ components: If unlimited=true the subject can use the feature an unlimited amount. usagePeriod: $ref: "#/components/schemas/RecurringPeriodCreateInput" - # Mixed feelings about adding this, rest is not an intent driven convention issueAfterReset: type: number format: double description: | You can issue usage automatically after reset. This usage is not rolled over. + issueAfterResetPriority: + type: integer + minimum: 1 + maximum: 255 + default: 1 + example: 1 + description: | + Defines the grant priority for the default grant. If provided, issueAfterReset must have a value. EntitlementCreateInputs: oneOf: - $ref: "#/components/schemas/EntitlementMeteredCreateInputs" diff --git a/e2e/e2e_test.go b/e2e/e2e_test.go index 6acbf2c38..f41bc23db 100644 --- a/e2e/e2e_test.go +++ b/e2e/e2e_test.go @@ -555,6 +555,46 @@ func TestCredit(t *testing.T) { require.Equal(t, *entitlementId, resp.ApplicationproblemJSON409.Extensions.ConflictingEntityId) }) + t.Run("Create a Entitlement With Default Grants", func(t *testing.T) { + randSubject := ulid.Make().String() + meteredEntitlement := api.EntitlementMeteredCreateInputs{ + Type: "metered", + FeatureId: featureId, + UsagePeriod: api.RecurringPeriodCreateInput{ + Anchor: convert.ToPointer(time.Date(2024, time.January, 1, 0, 0, 0, 0, time.UTC)), + Interval: "MONTH", + }, + IssueAfterReset: convert.ToPointer(100.0), + IssueAfterResetPriority: convert.ToPointer(6), + } + body := &api.CreateEntitlementJSONRequestBody{} + err := body.FromEntitlementMeteredCreateInputs(meteredEntitlement) + require.NoError(t, err) + resp, err := client.CreateEntitlementWithResponse(context.Background(), randSubject, *body) + + require.NoError(t, err) + require.Equal(t, http.StatusCreated, resp.StatusCode(), "Invalid status code [response_body=%s]", string(resp.Body)) + + metered, err := resp.JSON201.AsEntitlementMetered() + require.NoError(t, err) + + require.Equal(t, randSubject, metered.SubjectKey) + + // fetch grants for entitlement + grantListResp, err := client.ListEntitlementGrantsWithResponse(context.Background(), randSubject, *metered.Id, nil) + require.NoError(t, err) + require.Equal(t, http.StatusOK, grantListResp.StatusCode()) + require.NotNil(t, grantListResp.JSON200) + require.Len(t, *grantListResp.JSON200, 1) + + require.Equal(t, *metered.IssueAfterReset, (*grantListResp.JSON200)[0].Amount) + require.Equal(t, metered.IssueAfterResetPriority, (*grantListResp.JSON200)[0].Priority) + require.Equal(t, metered.Id, (*grantListResp.JSON200)[0].EntitlementId) + require.Equal(t, map[string]string{ + "issueAfterReset": "true", + }, *(*grantListResp.JSON200)[0].Metadata) + }) + t.Run("Create Grant", func(t *testing.T) { effectiveAt := time.Now().Truncate(time.Minute) @@ -679,7 +719,7 @@ func TestCredit(t *testing.T) { t.Run("Entitlement Value", func(t *testing.T) { // Get grants - grantListResp, err := client.ListGrantsWithResponse(context.Background(), &api.ListGrantsParams{}) + grantListResp, err := client.ListEntitlementGrantsWithResponse(context.Background(), subject, *entitlementId, nil) require.NoError(t, err) require.Equal(t, http.StatusOK, grantListResp.StatusCode()) require.NotNil(t, grantListResp.JSON200) @@ -714,7 +754,7 @@ func TestCredit(t *testing.T) { effectiveAt := time.Now().Truncate(time.Minute) // Get grants - grantListResp, err := client.ListGrantsWithResponse(context.Background(), &api.ListGrantsParams{}) + grantListResp, err := client.ListEntitlementGrantsWithResponse(context.Background(), subject, *entitlementId, nil) require.NoError(t, err) require.Equal(t, http.StatusOK, grantListResp.StatusCode()) require.NotNil(t, grantListResp.JSON200) diff --git a/internal/credit/grant.go b/internal/credit/grant.go index df90e14e7..3acebb0a7 100644 --- a/internal/credit/grant.go +++ b/internal/credit/grant.go @@ -22,10 +22,6 @@ func (n NamespacedGrantOwner) NamespacedID() models.NamespacedID { } } -const ( - GrantPriorityDefault uint8 = 1 -) - // Grant is an immutable definition used to increase balance. type Grant struct { models.ManagedModel diff --git a/internal/entitlement/entitlement.go b/internal/entitlement/entitlement.go index b32f9831f..1987e4b98 100644 --- a/internal/entitlement/entitlement.go +++ b/internal/entitlement/entitlement.go @@ -20,11 +20,12 @@ type CreateEntitlementInputs struct { EntitlementType EntitlementType `json:"type"` Metadata map[string]string `json:"metadata,omitempty"` - MeasureUsageFrom *time.Time `json:"measureUsageFrom,omitempty"` - IssueAfterReset *float64 `json:"issueAfterReset,omitempty"` - IsSoftLimit *bool `json:"isSoftLimit,omitempty"` - Config []byte `json:"config,omitempty"` - UsagePeriod *UsagePeriod `json:"usagePeriod,omitempty"` + MeasureUsageFrom *time.Time `json:"measureUsageFrom,omitempty"` + IssueAfterReset *float64 `json:"issueAfterReset,omitempty"` + IssueAfterResetPriority *uint8 `json:"issueAfterResetPriority,omitempty"` + IsSoftLimit *bool `json:"isSoftLimit,omitempty"` + Config []byte `json:"config,omitempty"` + UsagePeriod *UsagePeriod `json:"usagePeriod,omitempty"` } func (c CreateEntitlementInputs) GetType() EntitlementType { @@ -37,10 +38,11 @@ type Entitlement struct { // All none-core fields are optional // metered - MeasureUsageFrom *time.Time `json:"_,omitempty"` - IssueAfterReset *float64 `json:"issueAfterReset,omitempty"` - IsSoftLimit *bool `json:"isSoftLimit,omitempty"` - LastReset *time.Time `json:"lastReset,omitempty"` + MeasureUsageFrom *time.Time `json:"_,omitempty"` + IssueAfterReset *float64 `json:"issueAfterReset,omitempty"` + IssueAfterResetPriority *uint8 `json:"issueAfterResetPriority,omitempty"` + IsSoftLimit *bool `json:"isSoftLimit,omitempty"` + LastReset *time.Time `json:"lastReset,omitempty"` // static Config []byte `json:"config,omitempty"` diff --git a/internal/entitlement/httpdriver/entitlement.go b/internal/entitlement/httpdriver/entitlement.go index 019d00374..115cc4846 100644 --- a/internal/entitlement/httpdriver/entitlement.go +++ b/internal/entitlement/httpdriver/entitlement.go @@ -83,6 +83,9 @@ func (h *entitlementHandler) CreateEntitlement() CreateEntitlementHandler { EntitlementType: entitlement.EntitlementTypeMetered, IsSoftLimit: v.IsSoftLimit, IssueAfterReset: v.IssueAfterReset, + IssueAfterResetPriority: convert.SafeDeRef(v.IssueAfterResetPriority, func(i int) *uint8 { + return convert.ToPointer(uint8(i)) + }), UsagePeriod: &entitlement.UsagePeriod{ Anchor: defaultx.WithDefault(v.UsagePeriod.Anchor, clock.Now()), // TODO: shouldn't we truncate this? Interval: recurrence.RecurrenceInterval(v.UsagePeriod.Interval), diff --git a/internal/entitlement/httpdriver/parser.go b/internal/entitlement/httpdriver/parser.go index 8c85b1dba..84d58712c 100644 --- a/internal/entitlement/httpdriver/parser.go +++ b/internal/entitlement/httpdriver/parser.go @@ -23,14 +23,21 @@ func (parser) ToMetered(e *entitlement.Entitlement) (*api.EntitlementMetered, er } return &api.EntitlementMetered{ - CreatedAt: &metered.CreatedAt, - DeletedAt: metered.DeletedAt, - FeatureId: metered.FeatureID, - FeatureKey: metered.FeatureKey, - Id: &metered.ID, - IsSoftLimit: convert.ToPointer(metered.IsSoftLimit), - IsUnlimited: convert.ToPointer(false), // implement - IssueAfterReset: metered.IssuesAfterReset, + CreatedAt: &metered.CreatedAt, + DeletedAt: metered.DeletedAt, + FeatureId: metered.FeatureID, + FeatureKey: metered.FeatureKey, + Id: &metered.ID, + IsSoftLimit: convert.ToPointer(metered.IsSoftLimit), + IsUnlimited: convert.ToPointer(false), // implement + IssueAfterReset: convert.SafeDeRef(metered.IssueAfterReset, func(i meteredentitlement.IssueAfterReset) *float64 { + return &i.Amount + }), + IssueAfterResetPriority: convert.SafeDeRef(metered.IssueAfterReset, func(i meteredentitlement.IssueAfterReset) *int { + return convert.SafeDeRef(i.Priority, func(p uint8) *int { + return convert.ToPointer(int(p)) + }) + }), Metadata: convert.MapToPointer(metered.Metadata), SubjectKey: metered.SubjectKey, Type: api.EntitlementMeteredType(metered.EntitlementType), diff --git a/internal/entitlement/metered/connector.go b/internal/entitlement/metered/connector.go index 0f1009023..b84f7292c 100644 --- a/internal/entitlement/metered/connector.go +++ b/internal/entitlement/metered/connector.go @@ -118,6 +118,10 @@ func (c *connector) BeforeCreate(model entitlement.CreateEntitlementInputs, feat return nil, &entitlement.InvalidFeatureError{FeatureID: feature.ID, Message: "Feature has no meter"} } + if model.IssueAfterResetPriority != nil && model.IssueAfterReset == nil { + return nil, &entitlement.InvalidValueError{Type: model.EntitlementType, Message: "IssueAfterResetPriority requires IssueAfterReset"} + } + model.MeasureUsageFrom = convert.ToPointer(defaultx.WithDefault(model.MeasureUsageFrom, clock.Now().Truncate(c.granularity))) model.IsSoftLimit = convert.ToPointer(defaultx.WithDefault(model.IsSoftLimit, false)) model.IssueAfterReset = convert.ToPointer(defaultx.WithDefault(model.IssueAfterReset, 0.0)) @@ -138,17 +142,18 @@ func (c *connector) BeforeCreate(model entitlement.CreateEntitlementInputs, feat currentPeriod.From = *model.MeasureUsageFrom return &entitlement.CreateEntitlementRepoInputs{ - Namespace: model.Namespace, - FeatureID: feature.ID, - FeatureKey: feature.Key, - SubjectKey: model.SubjectKey, - EntitlementType: model.EntitlementType, - Metadata: model.Metadata, - MeasureUsageFrom: model.MeasureUsageFrom, - IssueAfterReset: model.IssueAfterReset, - IsSoftLimit: model.IsSoftLimit, - UsagePeriod: model.UsagePeriod, - CurrentUsagePeriod: ¤tPeriod, + Namespace: model.Namespace, + FeatureID: feature.ID, + FeatureKey: feature.Key, + SubjectKey: model.SubjectKey, + EntitlementType: model.EntitlementType, + Metadata: model.Metadata, + MeasureUsageFrom: model.MeasureUsageFrom, + IssueAfterReset: model.IssueAfterReset, + IssueAfterResetPriority: model.IssueAfterResetPriority, + IsSoftLimit: model.IsSoftLimit, + UsagePeriod: model.UsagePeriod, + CurrentUsagePeriod: ¤tPeriod, }, nil } @@ -162,15 +167,18 @@ func (c *connector) AfterCreate(ctx context.Context, end *entitlement.Entitlemen // Until we refactor and fix this, to avoid any potential errors due to changes in downstream connectors, the code is inlined here. // issue default grants if metered.HasDefaultGrant() { - amountToIssue := *metered.IssuesAfterReset - effectiveAt := metered.CurrentUsagePeriod.From + if metered.IssueAfterReset == nil { + return fmt.Errorf("inconsistency error: entitlement %s should have default grant but has no IssueAfterReset", metered.ID) + } + effectiveAt := metered.CurrentUsagePeriod.From + amountToIssue := metered.IssueAfterReset.Amount _, err := c.grantConnector.CreateGrant(ctx, credit.NamespacedGrantOwner{ Namespace: metered.Namespace, ID: credit.GrantOwner(metered.ID), }, credit.CreateGrantInput{ Amount: amountToIssue, - Priority: credit.GrantPriorityDefault, + Priority: defaultx.WithDefault(metered.IssueAfterReset.Priority, DefaultIssueAfterResetPriority), EffectiveAt: effectiveAt, Expiration: credit.ExpirationPeriod{ Count: 100, // This is a bit of an issue... It would make sense for recurring tags to not have an expiration @@ -179,6 +187,9 @@ func (c *connector) AfterCreate(ctx context.Context, end *entitlement.Entitlemen // These two in conjunction make the grant always have `amountToIssue` balance after a reset ResetMaxRollover: amountToIssue, ResetMinRollover: amountToIssue, + Metadata: map[string]string{ + IssueAfterResetMetaTag: "true", + }, }) if err != nil { return err diff --git a/internal/entitlement/metered/entitlement.go b/internal/entitlement/metered/entitlement.go index 21fbd8459..45f793bd3 100644 --- a/internal/entitlement/metered/entitlement.go +++ b/internal/entitlement/metered/entitlement.go @@ -7,6 +7,17 @@ import ( "github.com/openmeterio/openmeter/pkg/recurrence" ) +const ( + DefaultIssueAfterResetPriority = 1 + IssueAfterResetMetaTag = "issueAfterReset" +) + +// IssueAfterReset defines a default grant's parameters that can be created alongside an entitlement to set up a default balance. +type IssueAfterReset struct { + Amount float64 `json:"amount"` + Priority *uint8 `json:"priority,omitempty"` +} + type Entitlement struct { entitlement.GenericProperties @@ -14,9 +25,8 @@ type Entitlement struct { // This is a global value, in most cases the same value as `CreatedAt` should be fine. MeasureUsageFrom time.Time `json:"measureUsageFrom,omitempty"` - // IssueAfterReset defines an amount of usage that will be issued after a reset. - // This affordance will only be usable until the next reset. - IssuesAfterReset *float64 `json:"issueAfterReset,omitempty"` + // Sets up a default grant + IssueAfterReset *IssueAfterReset `json:"issueAfterReset,omitempty"` // IsSoftLimit defines if the entitlement is a soft limit. By default when balance falls to 0 // access will be disabled. If this is a soft limit, access will be allowed nonetheless. @@ -33,9 +43,9 @@ type Entitlement struct { } // HasDefaultGrant returns true if the entitlement has a default grant. -// This is the case when `IssuesAfterReset` is set and greater than 0. +// This is the case when `IssueAfterReset` is set and greater than 0. func (e *Entitlement) HasDefaultGrant() bool { - return e.IssuesAfterReset != nil && *e.IssuesAfterReset > 0 + return e.IssueAfterReset != nil && e.IssueAfterReset.Amount > 0 } func ParseFromGenericEntitlement(model *entitlement.Entitlement) (*Entitlement, error) { @@ -63,14 +73,26 @@ func ParseFromGenericEntitlement(model *entitlement.Entitlement) (*Entitlement, return nil, &entitlement.InvalidValueError{Message: "CurrentUsagePeriod is required", Type: model.EntitlementType} } - return &Entitlement{ + if model.IssueAfterResetPriority != nil && model.IssueAfterReset == nil { + return nil, &entitlement.InvalidValueError{Message: "IssueAfterReset is required for IssueAfterResetPriority", Type: model.EntitlementType} + } + + ent := Entitlement{ GenericProperties: model.GenericProperties, MeasureUsageFrom: *model.MeasureUsageFrom, - IssuesAfterReset: model.IssueAfterReset, IsSoftLimit: *model.IsSoftLimit, UsagePeriod: *model.UsagePeriod, LastReset: *model.LastReset, CurrentUsagePeriod: *model.CurrentUsagePeriod, - }, nil + } + + if model.IssueAfterReset != nil { + ent.IssueAfterReset = &IssueAfterReset{ + Amount: *model.IssueAfterReset, + Priority: model.IssueAfterResetPriority, + } + } + + return &ent, nil } diff --git a/internal/entitlement/postgresadapter/ent/db/entitlement.go b/internal/entitlement/postgresadapter/ent/db/entitlement.go index 5b05d5744..0e0c5f71e 100644 --- a/internal/entitlement/postgresadapter/ent/db/entitlement.go +++ b/internal/entitlement/postgresadapter/ent/db/entitlement.go @@ -40,6 +40,8 @@ type Entitlement struct { MeasureUsageFrom *time.Time `json:"measure_usage_from,omitempty"` // IssueAfterReset holds the value of the "issue_after_reset" field. IssueAfterReset *float64 `json:"issue_after_reset,omitempty"` + // IssueAfterResetPriority holds the value of the "issue_after_reset_priority" field. + IssueAfterResetPriority *uint8 `json:"issue_after_reset_priority,omitempty"` // IsSoftLimit holds the value of the "is_soft_limit" field. IsSoftLimit *bool `json:"is_soft_limit,omitempty"` // Config holds the value of the "config" field. @@ -87,6 +89,8 @@ func (*Entitlement) scanValues(columns []string) ([]any, error) { values[i] = new(sql.NullBool) case entitlement.FieldIssueAfterReset: values[i] = new(sql.NullFloat64) + case entitlement.FieldIssueAfterResetPriority: + values[i] = new(sql.NullInt64) case entitlement.FieldID, entitlement.FieldNamespace, entitlement.FieldEntitlementType, entitlement.FieldFeatureID, entitlement.FieldFeatureKey, entitlement.FieldSubjectKey, entitlement.FieldUsagePeriodInterval: values[i] = new(sql.NullString) case entitlement.FieldCreatedAt, entitlement.FieldUpdatedAt, entitlement.FieldDeletedAt, entitlement.FieldMeasureUsageFrom, entitlement.FieldUsagePeriodAnchor, entitlement.FieldCurrentUsagePeriodStart, entitlement.FieldCurrentUsagePeriodEnd: @@ -183,6 +187,13 @@ func (e *Entitlement) assignValues(columns []string, values []any) error { e.IssueAfterReset = new(float64) *e.IssueAfterReset = value.Float64 } + case entitlement.FieldIssueAfterResetPriority: + if value, ok := values[i].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field issue_after_reset_priority", values[i]) + } else if value.Valid { + e.IssueAfterResetPriority = new(uint8) + *e.IssueAfterResetPriority = uint8(value.Int64) + } case entitlement.FieldIsSoftLimit: if value, ok := values[i].(*sql.NullBool); !ok { return fmt.Errorf("unexpected type %T for field is_soft_limit", values[i]) @@ -306,6 +317,11 @@ func (e *Entitlement) String() string { builder.WriteString(fmt.Sprintf("%v", *v)) } builder.WriteString(", ") + if v := e.IssueAfterResetPriority; v != nil { + builder.WriteString("issue_after_reset_priority=") + builder.WriteString(fmt.Sprintf("%v", *v)) + } + builder.WriteString(", ") if v := e.IsSoftLimit; v != nil { builder.WriteString("is_soft_limit=") builder.WriteString(fmt.Sprintf("%v", *v)) diff --git a/internal/entitlement/postgresadapter/ent/db/entitlement/entitlement.go b/internal/entitlement/postgresadapter/ent/db/entitlement/entitlement.go index 0267412ad..616b3bd55 100644 --- a/internal/entitlement/postgresadapter/ent/db/entitlement/entitlement.go +++ b/internal/entitlement/postgresadapter/ent/db/entitlement/entitlement.go @@ -37,6 +37,8 @@ const ( FieldMeasureUsageFrom = "measure_usage_from" // FieldIssueAfterReset holds the string denoting the issue_after_reset field in the database. FieldIssueAfterReset = "issue_after_reset" + // FieldIssueAfterResetPriority holds the string denoting the issue_after_reset_priority field in the database. + FieldIssueAfterResetPriority = "issue_after_reset_priority" // FieldIsSoftLimit holds the string denoting the is_soft_limit field in the database. FieldIsSoftLimit = "is_soft_limit" // FieldConfig holds the string denoting the config field in the database. @@ -76,6 +78,7 @@ var Columns = []string{ FieldSubjectKey, FieldMeasureUsageFrom, FieldIssueAfterReset, + FieldIssueAfterResetPriority, FieldIsSoftLimit, FieldConfig, FieldUsagePeriodInterval, @@ -218,6 +221,11 @@ func ByIssueAfterReset(opts ...sql.OrderTermOption) OrderOption { return sql.OrderByField(FieldIssueAfterReset, opts...).ToFunc() } +// ByIssueAfterResetPriority orders the results by the issue_after_reset_priority field. +func ByIssueAfterResetPriority(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldIssueAfterResetPriority, opts...).ToFunc() +} + // ByIsSoftLimit orders the results by the is_soft_limit field. func ByIsSoftLimit(opts ...sql.OrderTermOption) OrderOption { return sql.OrderByField(FieldIsSoftLimit, opts...).ToFunc() diff --git a/internal/entitlement/postgresadapter/ent/db/entitlement/where.go b/internal/entitlement/postgresadapter/ent/db/entitlement/where.go index fec305bd3..f0c432df5 100644 --- a/internal/entitlement/postgresadapter/ent/db/entitlement/where.go +++ b/internal/entitlement/postgresadapter/ent/db/entitlement/where.go @@ -110,6 +110,11 @@ func IssueAfterReset(v float64) predicate.Entitlement { return predicate.Entitlement(sql.FieldEQ(FieldIssueAfterReset, v)) } +// IssueAfterResetPriority applies equality check predicate on the "issue_after_reset_priority" field. It's identical to IssueAfterResetPriorityEQ. +func IssueAfterResetPriority(v uint8) predicate.Entitlement { + return predicate.Entitlement(sql.FieldEQ(FieldIssueAfterResetPriority, v)) +} + // IsSoftLimit applies equality check predicate on the "is_soft_limit" field. It's identical to IsSoftLimitEQ. func IsSoftLimit(v bool) predicate.Entitlement { return predicate.Entitlement(sql.FieldEQ(FieldIsSoftLimit, v)) @@ -650,6 +655,56 @@ func IssueAfterResetNotNil() predicate.Entitlement { return predicate.Entitlement(sql.FieldNotNull(FieldIssueAfterReset)) } +// IssueAfterResetPriorityEQ applies the EQ predicate on the "issue_after_reset_priority" field. +func IssueAfterResetPriorityEQ(v uint8) predicate.Entitlement { + return predicate.Entitlement(sql.FieldEQ(FieldIssueAfterResetPriority, v)) +} + +// IssueAfterResetPriorityNEQ applies the NEQ predicate on the "issue_after_reset_priority" field. +func IssueAfterResetPriorityNEQ(v uint8) predicate.Entitlement { + return predicate.Entitlement(sql.FieldNEQ(FieldIssueAfterResetPriority, v)) +} + +// IssueAfterResetPriorityIn applies the In predicate on the "issue_after_reset_priority" field. +func IssueAfterResetPriorityIn(vs ...uint8) predicate.Entitlement { + return predicate.Entitlement(sql.FieldIn(FieldIssueAfterResetPriority, vs...)) +} + +// IssueAfterResetPriorityNotIn applies the NotIn predicate on the "issue_after_reset_priority" field. +func IssueAfterResetPriorityNotIn(vs ...uint8) predicate.Entitlement { + return predicate.Entitlement(sql.FieldNotIn(FieldIssueAfterResetPriority, vs...)) +} + +// IssueAfterResetPriorityGT applies the GT predicate on the "issue_after_reset_priority" field. +func IssueAfterResetPriorityGT(v uint8) predicate.Entitlement { + return predicate.Entitlement(sql.FieldGT(FieldIssueAfterResetPriority, v)) +} + +// IssueAfterResetPriorityGTE applies the GTE predicate on the "issue_after_reset_priority" field. +func IssueAfterResetPriorityGTE(v uint8) predicate.Entitlement { + return predicate.Entitlement(sql.FieldGTE(FieldIssueAfterResetPriority, v)) +} + +// IssueAfterResetPriorityLT applies the LT predicate on the "issue_after_reset_priority" field. +func IssueAfterResetPriorityLT(v uint8) predicate.Entitlement { + return predicate.Entitlement(sql.FieldLT(FieldIssueAfterResetPriority, v)) +} + +// IssueAfterResetPriorityLTE applies the LTE predicate on the "issue_after_reset_priority" field. +func IssueAfterResetPriorityLTE(v uint8) predicate.Entitlement { + return predicate.Entitlement(sql.FieldLTE(FieldIssueAfterResetPriority, v)) +} + +// IssueAfterResetPriorityIsNil applies the IsNil predicate on the "issue_after_reset_priority" field. +func IssueAfterResetPriorityIsNil() predicate.Entitlement { + return predicate.Entitlement(sql.FieldIsNull(FieldIssueAfterResetPriority)) +} + +// IssueAfterResetPriorityNotNil applies the NotNil predicate on the "issue_after_reset_priority" field. +func IssueAfterResetPriorityNotNil() predicate.Entitlement { + return predicate.Entitlement(sql.FieldNotNull(FieldIssueAfterResetPriority)) +} + // IsSoftLimitEQ applies the EQ predicate on the "is_soft_limit" field. func IsSoftLimitEQ(v bool) predicate.Entitlement { return predicate.Entitlement(sql.FieldEQ(FieldIsSoftLimit, v)) diff --git a/internal/entitlement/postgresadapter/ent/db/entitlement_create.go b/internal/entitlement/postgresadapter/ent/db/entitlement_create.go index 2e96ec8c2..54db4cdf0 100644 --- a/internal/entitlement/postgresadapter/ent/db/entitlement_create.go +++ b/internal/entitlement/postgresadapter/ent/db/entitlement_create.go @@ -130,6 +130,20 @@ func (ec *EntitlementCreate) SetNillableIssueAfterReset(f *float64) *Entitlement return ec } +// SetIssueAfterResetPriority sets the "issue_after_reset_priority" field. +func (ec *EntitlementCreate) SetIssueAfterResetPriority(u uint8) *EntitlementCreate { + ec.mutation.SetIssueAfterResetPriority(u) + return ec +} + +// SetNillableIssueAfterResetPriority sets the "issue_after_reset_priority" field if the given value is not nil. +func (ec *EntitlementCreate) SetNillableIssueAfterResetPriority(u *uint8) *EntitlementCreate { + if u != nil { + ec.SetIssueAfterResetPriority(*u) + } + return ec +} + // SetIsSoftLimit sets the "is_soft_limit" field. func (ec *EntitlementCreate) SetIsSoftLimit(b bool) *EntitlementCreate { ec.mutation.SetIsSoftLimit(b) @@ -412,6 +426,10 @@ func (ec *EntitlementCreate) createSpec() (*Entitlement, *sqlgraph.CreateSpec) { _spec.SetField(entitlement.FieldIssueAfterReset, field.TypeFloat64, value) _node.IssueAfterReset = &value } + if value, ok := ec.mutation.IssueAfterResetPriority(); ok { + _spec.SetField(entitlement.FieldIssueAfterResetPriority, field.TypeUint8, value) + _node.IssueAfterResetPriority = &value + } if value, ok := ec.mutation.IsSoftLimit(); ok { _spec.SetField(entitlement.FieldIsSoftLimit, field.TypeBool, value) _node.IsSoftLimit = &value @@ -665,6 +683,9 @@ func (u *EntitlementUpsertOne) UpdateNewValues() *EntitlementUpsertOne { if _, exists := u.create.mutation.IssueAfterReset(); exists { s.SetIgnore(entitlement.FieldIssueAfterReset) } + if _, exists := u.create.mutation.IssueAfterResetPriority(); exists { + s.SetIgnore(entitlement.FieldIssueAfterResetPriority) + } if _, exists := u.create.mutation.IsSoftLimit(); exists { s.SetIgnore(entitlement.FieldIsSoftLimit) } @@ -1049,6 +1070,9 @@ func (u *EntitlementUpsertBulk) UpdateNewValues() *EntitlementUpsertBulk { if _, exists := b.mutation.IssueAfterReset(); exists { s.SetIgnore(entitlement.FieldIssueAfterReset) } + if _, exists := b.mutation.IssueAfterResetPriority(); exists { + s.SetIgnore(entitlement.FieldIssueAfterResetPriority) + } if _, exists := b.mutation.IsSoftLimit(); exists { s.SetIgnore(entitlement.FieldIsSoftLimit) } diff --git a/internal/entitlement/postgresadapter/ent/db/entitlement_update.go b/internal/entitlement/postgresadapter/ent/db/entitlement_update.go index 51a8ba761..70dd6218e 100644 --- a/internal/entitlement/postgresadapter/ent/db/entitlement_update.go +++ b/internal/entitlement/postgresadapter/ent/db/entitlement_update.go @@ -253,6 +253,9 @@ func (eu *EntitlementUpdate) sqlSave(ctx context.Context) (n int, err error) { if eu.mutation.IssueAfterResetCleared() { _spec.ClearField(entitlement.FieldIssueAfterReset, field.TypeFloat64) } + if eu.mutation.IssueAfterResetPriorityCleared() { + _spec.ClearField(entitlement.FieldIssueAfterResetPriority, field.TypeUint8) + } if eu.mutation.IsSoftLimitCleared() { _spec.ClearField(entitlement.FieldIsSoftLimit, field.TypeBool) } @@ -606,6 +609,9 @@ func (euo *EntitlementUpdateOne) sqlSave(ctx context.Context) (_node *Entitlemen if euo.mutation.IssueAfterResetCleared() { _spec.ClearField(entitlement.FieldIssueAfterReset, field.TypeFloat64) } + if euo.mutation.IssueAfterResetPriorityCleared() { + _spec.ClearField(entitlement.FieldIssueAfterResetPriority, field.TypeUint8) + } if euo.mutation.IsSoftLimitCleared() { _spec.ClearField(entitlement.FieldIsSoftLimit, field.TypeBool) } diff --git a/internal/entitlement/postgresadapter/ent/db/migrate/schema.go b/internal/entitlement/postgresadapter/ent/db/migrate/schema.go index 2491dbd9e..9b508bf37 100644 --- a/internal/entitlement/postgresadapter/ent/db/migrate/schema.go +++ b/internal/entitlement/postgresadapter/ent/db/migrate/schema.go @@ -22,6 +22,7 @@ var ( {Name: "subject_key", Type: field.TypeString}, {Name: "measure_usage_from", Type: field.TypeTime, Nullable: true}, {Name: "issue_after_reset", Type: field.TypeFloat64, Nullable: true}, + {Name: "issue_after_reset_priority", Type: field.TypeUint8, Nullable: true}, {Name: "is_soft_limit", Type: field.TypeBool, Nullable: true}, {Name: "config", Type: field.TypeJSON, Nullable: true, SchemaType: map[string]string{"postgres": "jsonb"}}, {Name: "usage_period_interval", Type: field.TypeEnum, Nullable: true, Enums: []string{"DAY", "WEEK", "MONTH", "YEAR"}}, @@ -63,7 +64,7 @@ var ( { Name: "entitlement_namespace_current_usage_period_end", Unique: false, - Columns: []*schema.Column{EntitlementsColumns[1], EntitlementsColumns[17]}, + Columns: []*schema.Column{EntitlementsColumns[1], EntitlementsColumns[18]}, }, }, } diff --git a/internal/entitlement/postgresadapter/ent/db/mutation.go b/internal/entitlement/postgresadapter/ent/db/mutation.go index 7603b86d4..fee6fc63d 100644 --- a/internal/entitlement/postgresadapter/ent/db/mutation.go +++ b/internal/entitlement/postgresadapter/ent/db/mutation.go @@ -32,35 +32,37 @@ const ( // EntitlementMutation represents an operation that mutates the Entitlement nodes in the graph. type EntitlementMutation struct { config - op Op - typ string - id *string - namespace *string - metadata *map[string]string - created_at *time.Time - updated_at *time.Time - deleted_at *time.Time - entitlement_type *entitlement.EntitlementType - feature_id *string - feature_key *string - subject_key *string - measure_usage_from *time.Time - issue_after_reset *float64 - addissue_after_reset *float64 - is_soft_limit *bool - _config *[]uint8 - append_config []uint8 - usage_period_interval *entitlement.UsagePeriodInterval - usage_period_anchor *time.Time - current_usage_period_start *time.Time - current_usage_period_end *time.Time - clearedFields map[string]struct{} - usage_reset map[string]struct{} - removedusage_reset map[string]struct{} - clearedusage_reset bool - done bool - oldValue func(context.Context) (*Entitlement, error) - predicates []predicate.Entitlement + op Op + typ string + id *string + namespace *string + metadata *map[string]string + created_at *time.Time + updated_at *time.Time + deleted_at *time.Time + entitlement_type *entitlement.EntitlementType + feature_id *string + feature_key *string + subject_key *string + measure_usage_from *time.Time + issue_after_reset *float64 + addissue_after_reset *float64 + issue_after_reset_priority *uint8 + addissue_after_reset_priority *int8 + is_soft_limit *bool + _config *[]uint8 + append_config []uint8 + usage_period_interval *entitlement.UsagePeriodInterval + usage_period_anchor *time.Time + current_usage_period_start *time.Time + current_usage_period_end *time.Time + clearedFields map[string]struct{} + usage_reset map[string]struct{} + removedusage_reset map[string]struct{} + clearedusage_reset bool + done bool + oldValue func(context.Context) (*Entitlement, error) + predicates []predicate.Entitlement } var _ ent.Mutation = (*EntitlementMutation)(nil) @@ -636,6 +638,76 @@ func (m *EntitlementMutation) ResetIssueAfterReset() { delete(m.clearedFields, entitlement.FieldIssueAfterReset) } +// SetIssueAfterResetPriority sets the "issue_after_reset_priority" field. +func (m *EntitlementMutation) SetIssueAfterResetPriority(u uint8) { + m.issue_after_reset_priority = &u + m.addissue_after_reset_priority = nil +} + +// IssueAfterResetPriority returns the value of the "issue_after_reset_priority" field in the mutation. +func (m *EntitlementMutation) IssueAfterResetPriority() (r uint8, exists bool) { + v := m.issue_after_reset_priority + if v == nil { + return + } + return *v, true +} + +// OldIssueAfterResetPriority returns the old "issue_after_reset_priority" field's value of the Entitlement entity. +// If the Entitlement object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *EntitlementMutation) OldIssueAfterResetPriority(ctx context.Context) (v *uint8, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldIssueAfterResetPriority is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldIssueAfterResetPriority requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldIssueAfterResetPriority: %w", err) + } + return oldValue.IssueAfterResetPriority, nil +} + +// AddIssueAfterResetPriority adds u to the "issue_after_reset_priority" field. +func (m *EntitlementMutation) AddIssueAfterResetPriority(u int8) { + if m.addissue_after_reset_priority != nil { + *m.addissue_after_reset_priority += u + } else { + m.addissue_after_reset_priority = &u + } +} + +// AddedIssueAfterResetPriority returns the value that was added to the "issue_after_reset_priority" field in this mutation. +func (m *EntitlementMutation) AddedIssueAfterResetPriority() (r int8, exists bool) { + v := m.addissue_after_reset_priority + if v == nil { + return + } + return *v, true +} + +// ClearIssueAfterResetPriority clears the value of the "issue_after_reset_priority" field. +func (m *EntitlementMutation) ClearIssueAfterResetPriority() { + m.issue_after_reset_priority = nil + m.addissue_after_reset_priority = nil + m.clearedFields[entitlement.FieldIssueAfterResetPriority] = struct{}{} +} + +// IssueAfterResetPriorityCleared returns if the "issue_after_reset_priority" field was cleared in this mutation. +func (m *EntitlementMutation) IssueAfterResetPriorityCleared() bool { + _, ok := m.clearedFields[entitlement.FieldIssueAfterResetPriority] + return ok +} + +// ResetIssueAfterResetPriority resets all changes to the "issue_after_reset_priority" field. +func (m *EntitlementMutation) ResetIssueAfterResetPriority() { + m.issue_after_reset_priority = nil + m.addissue_after_reset_priority = nil + delete(m.clearedFields, entitlement.FieldIssueAfterResetPriority) +} + // SetIsSoftLimit sets the "is_soft_limit" field. func (m *EntitlementMutation) SetIsSoftLimit(b bool) { m.is_soft_limit = &b @@ -1034,7 +1106,7 @@ func (m *EntitlementMutation) Type() string { // order to get all numeric fields that were incremented/decremented, call // AddedFields(). func (m *EntitlementMutation) Fields() []string { - fields := make([]string, 0, 17) + fields := make([]string, 0, 18) if m.namespace != nil { fields = append(fields, entitlement.FieldNamespace) } @@ -1068,6 +1140,9 @@ func (m *EntitlementMutation) Fields() []string { if m.issue_after_reset != nil { fields = append(fields, entitlement.FieldIssueAfterReset) } + if m.issue_after_reset_priority != nil { + fields = append(fields, entitlement.FieldIssueAfterResetPriority) + } if m.is_soft_limit != nil { fields = append(fields, entitlement.FieldIsSoftLimit) } @@ -1116,6 +1191,8 @@ func (m *EntitlementMutation) Field(name string) (ent.Value, bool) { return m.MeasureUsageFrom() case entitlement.FieldIssueAfterReset: return m.IssueAfterReset() + case entitlement.FieldIssueAfterResetPriority: + return m.IssueAfterResetPriority() case entitlement.FieldIsSoftLimit: return m.IsSoftLimit() case entitlement.FieldConfig: @@ -1159,6 +1236,8 @@ func (m *EntitlementMutation) OldField(ctx context.Context, name string) (ent.Va return m.OldMeasureUsageFrom(ctx) case entitlement.FieldIssueAfterReset: return m.OldIssueAfterReset(ctx) + case entitlement.FieldIssueAfterResetPriority: + return m.OldIssueAfterResetPriority(ctx) case entitlement.FieldIsSoftLimit: return m.OldIsSoftLimit(ctx) case entitlement.FieldConfig: @@ -1257,6 +1336,13 @@ func (m *EntitlementMutation) SetField(name string, value ent.Value) error { } m.SetIssueAfterReset(v) return nil + case entitlement.FieldIssueAfterResetPriority: + v, ok := value.(uint8) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetIssueAfterResetPriority(v) + return nil case entitlement.FieldIsSoftLimit: v, ok := value.(bool) if !ok { @@ -1310,6 +1396,9 @@ func (m *EntitlementMutation) AddedFields() []string { if m.addissue_after_reset != nil { fields = append(fields, entitlement.FieldIssueAfterReset) } + if m.addissue_after_reset_priority != nil { + fields = append(fields, entitlement.FieldIssueAfterResetPriority) + } return fields } @@ -1320,6 +1409,8 @@ func (m *EntitlementMutation) AddedField(name string) (ent.Value, bool) { switch name { case entitlement.FieldIssueAfterReset: return m.AddedIssueAfterReset() + case entitlement.FieldIssueAfterResetPriority: + return m.AddedIssueAfterResetPriority() } return nil, false } @@ -1336,6 +1427,13 @@ func (m *EntitlementMutation) AddField(name string, value ent.Value) error { } m.AddIssueAfterReset(v) return nil + case entitlement.FieldIssueAfterResetPriority: + v, ok := value.(int8) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.AddIssueAfterResetPriority(v) + return nil } return fmt.Errorf("unknown Entitlement numeric field %s", name) } @@ -1356,6 +1454,9 @@ func (m *EntitlementMutation) ClearedFields() []string { if m.FieldCleared(entitlement.FieldIssueAfterReset) { fields = append(fields, entitlement.FieldIssueAfterReset) } + if m.FieldCleared(entitlement.FieldIssueAfterResetPriority) { + fields = append(fields, entitlement.FieldIssueAfterResetPriority) + } if m.FieldCleared(entitlement.FieldIsSoftLimit) { fields = append(fields, entitlement.FieldIsSoftLimit) } @@ -1400,6 +1501,9 @@ func (m *EntitlementMutation) ClearField(name string) error { case entitlement.FieldIssueAfterReset: m.ClearIssueAfterReset() return nil + case entitlement.FieldIssueAfterResetPriority: + m.ClearIssueAfterResetPriority() + return nil case entitlement.FieldIsSoftLimit: m.ClearIsSoftLimit() return nil @@ -1459,6 +1563,9 @@ func (m *EntitlementMutation) ResetField(name string) error { case entitlement.FieldIssueAfterReset: m.ResetIssueAfterReset() return nil + case entitlement.FieldIssueAfterResetPriority: + m.ResetIssueAfterResetPriority() + return nil case entitlement.FieldIsSoftLimit: m.ResetIsSoftLimit() return nil diff --git a/internal/entitlement/postgresadapter/ent/schema/entitlement.go b/internal/entitlement/postgresadapter/ent/schema/entitlement.go index 85aa250fb..4707a80d7 100644 --- a/internal/entitlement/postgresadapter/ent/schema/entitlement.go +++ b/internal/entitlement/postgresadapter/ent/schema/entitlement.go @@ -35,6 +35,7 @@ func (Entitlement) Fields() []ent.Field { field.String("subject_key").NotEmpty().Immutable(), field.Time("measure_usage_from").Optional().Nillable().Immutable(), field.Float("issue_after_reset").Optional().Nillable().Immutable(), + field.Uint8("issue_after_reset_priority").Optional().Nillable().Immutable(), field.Bool("is_soft_limit").Optional().Nillable().Immutable(), field.JSON("config", []byte{}).SchemaType(map[string]string{ dialect.Postgres: "jsonb", diff --git a/internal/entitlement/postgresadapter/entitlement.go b/internal/entitlement/postgresadapter/entitlement.go index f1db92f00..ad090b2f5 100644 --- a/internal/entitlement/postgresadapter/entitlement.go +++ b/internal/entitlement/postgresadapter/entitlement.go @@ -81,6 +81,7 @@ func (a *entitlementDBAdapter) CreateEntitlement(ctx context.Context, entitlemen SetFeatureKey(entitlement.FeatureKey). SetNillableMeasureUsageFrom(entitlement.MeasureUsageFrom). SetNillableIssueAfterReset(entitlement.IssueAfterReset). + SetNillableIssueAfterResetPriority(entitlement.IssueAfterResetPriority). SetNillableIsSoftLimit(entitlement.IsSoftLimit) if entitlement.UsagePeriod != nil { @@ -211,9 +212,10 @@ func mapEntitlementEntity(e *db.Entitlement) *entitlement.Entitlement { EntitlementType: entitlement.EntitlementType(e.EntitlementType), Metadata: e.Metadata, }, - MeasureUsageFrom: e.MeasureUsageFrom, - IssueAfterReset: e.IssueAfterReset, - IsSoftLimit: e.IsSoftLimit, + MeasureUsageFrom: e.MeasureUsageFrom, + IssueAfterReset: e.IssueAfterReset, + IssueAfterResetPriority: e.IssueAfterResetPriority, + IsSoftLimit: e.IsSoftLimit, } switch { diff --git a/internal/entitlement/repository.go b/internal/entitlement/repository.go index c9d480281..738c746b8 100644 --- a/internal/entitlement/repository.go +++ b/internal/entitlement/repository.go @@ -42,10 +42,11 @@ type CreateEntitlementRepoInputs struct { EntitlementType EntitlementType `json:"type"` Metadata map[string]string `json:"metadata,omitempty"` - MeasureUsageFrom *time.Time `json:"measureUsageFrom,omitempty"` - IssueAfterReset *float64 `json:"issueAfterReset,omitempty"` - IsSoftLimit *bool `json:"isSoftLimit,omitempty"` - Config []byte `json:"config,omitempty"` - UsagePeriod *UsagePeriod `json:"usagePeriod,omitempty"` - CurrentUsagePeriod *recurrence.Period `json:"currentUsagePeriod,omitempty"` + MeasureUsageFrom *time.Time `json:"measureUsageFrom,omitempty"` + IssueAfterReset *float64 `json:"issueAfterReset,omitempty"` + IssueAfterResetPriority *uint8 `json:"issueAfterResetPriority,omitempty"` + IsSoftLimit *bool `json:"isSoftLimit,omitempty"` + Config []byte `json:"config,omitempty"` + UsagePeriod *UsagePeriod `json:"usagePeriod,omitempty"` + CurrentUsagePeriod *recurrence.Period `json:"currentUsagePeriod,omitempty"` } diff --git a/pkg/convert/ptr.go b/pkg/convert/ptr.go index 3cc43929d..228d9f305 100644 --- a/pkg/convert/ptr.go +++ b/pkg/convert/ptr.go @@ -20,15 +20,16 @@ func ToStringLike[Source, Dest ~string](value *Source) *Dest { return ToPointer(Dest(*value)) } -func SafeConvert[T any, U any](value *T, fn func(T) U) *U { +// SafeDeRef is a helper function to safely dereference a pointer and apply a function to it. +func SafeDeRef[T any, U any](value *T, fn func(T) *U) *U { if value == nil { return nil } - return ToPointer(fn(*value)) + return fn(*value) } func SafeToUTC(t *time.Time) *time.Time { - return SafeConvert(t, func(dt time.Time) time.Time { - return dt.In(time.UTC) + return SafeDeRef(t, func(dt time.Time) *time.Time { + return ToPointer(dt.In(time.UTC)) }) }