mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-09-08 11:53:07 -04:00
Compare commits
616
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8d5912a5c4 | ||
|
|
b6f2adfffb | ||
|
|
9832ec25e5 | ||
|
|
c2a34e8c45 | ||
|
|
d6c6b6fd0d | ||
|
|
7f7a938c3f | ||
|
|
81536bbd0e | ||
|
|
be226ebb4c | ||
|
|
c2b37668e4 | ||
|
|
4b7c6908f0 | ||
|
|
6231a870d5 | ||
|
|
17003fe34b | ||
|
|
2ce9faec5a | ||
|
|
f5696d40f8 | ||
|
|
9a769b8019 | ||
|
|
bafbc88a40 | ||
|
|
addb32812a | ||
|
|
aa968ec898 | ||
|
|
61037cc22f | ||
|
|
993265b64e | ||
|
|
5995938c34 | ||
|
|
0a4f3ed786 | ||
|
|
a7214b3d73 | ||
|
|
81b0df1ad4 | ||
|
|
e6102c0405 | ||
|
|
ab0b3c58f1 | ||
|
|
3515594787 | ||
|
|
a8318fe03b | ||
|
|
706aaf02f2 | ||
|
|
88f21d804b | ||
|
|
8aebf80124 | ||
|
|
ae9fd595d9 | ||
|
|
709962b616 | ||
|
|
a2050d1fb9 | ||
|
|
0f4b95b9ae | ||
|
|
42876ca61c | ||
|
|
f5a064395a | ||
|
|
6688a037f7 | ||
|
|
20a579e6ea | ||
|
|
a52b55461e | ||
|
|
cc73c95a14 | ||
|
|
1ab6710e4c | ||
|
|
0750884597 | ||
|
|
aff81159a5 | ||
|
|
701d6fea17 | ||
|
|
74dd57d500 | ||
|
|
b95e341f9c | ||
|
|
67124a6c37 | ||
|
|
db4cee156b | ||
|
|
727c986de8 | ||
|
|
8d407417fe | ||
|
|
4a9b3f4002 | ||
|
|
71eb0716dc | ||
|
|
59fd05f0a9 | ||
|
|
3bd17299e3 | ||
|
|
cdc806d21c | ||
|
|
8997fbc326 | ||
|
|
df16f6d07f | ||
|
|
f60e2e52e5 | ||
|
|
249d105d27 | ||
|
|
5a7afe0bf6 | ||
|
|
000c99c63b | ||
|
|
df8d0e8fd3 | ||
|
|
f7c5d3adb4 | ||
|
|
e4365320de | ||
|
|
5b72318493 | ||
|
|
e8cf677353 | ||
|
|
d2bcd3cc9e | ||
|
|
71b3104e7b | ||
|
|
5f03dcf768 | ||
|
|
25043babd5 | ||
|
|
8bd130cc41 | ||
|
|
394b0fdc45 | ||
|
|
11d8b8a382 | ||
|
|
f0515bb28c | ||
|
|
d923bfe1f6 | ||
|
|
9822c1ffd4 | ||
|
|
c742ff6798 | ||
|
|
a2d5ee2bc6 | ||
|
|
7aa5b467f6 | ||
|
|
983c836653 | ||
|
|
7d4c6d6524 | ||
|
|
a249fa5f74 | ||
|
|
5e4f124e78 | ||
|
|
a1e8aa783d | ||
|
|
ae9ec4ce70 | ||
|
|
c03b9c7229 | ||
|
|
77bb974f9b | ||
|
|
1be01ae50c | ||
|
|
2b4a6fd739 | ||
|
|
7e0f536b83 | ||
|
|
49ebe072f1 | ||
|
|
8028e3e310 | ||
|
|
7d75b98c69 | ||
|
|
9e8403818c | ||
|
|
ef41429838 | ||
|
|
7bf64e329c | ||
|
|
268a4497b4 | ||
|
|
b4893baa81 | ||
|
|
ebf9566886 | ||
|
|
b149316349 | ||
|
|
c6ddc13055 | ||
|
|
65ea519099 | ||
|
|
2041fdc259 | ||
|
|
8e68a34b8f | ||
|
|
8f44f6eb42 | ||
|
|
0f9c6dc1ec | ||
|
|
5bfbfd8ff7 | ||
|
|
fe1e7632fa | ||
|
|
15b7fad504 | ||
|
|
5c97014cd2 | ||
|
|
774c732f52 | ||
|
|
95f175fe10 | ||
|
|
094baab7be | ||
|
|
feb13d426b | ||
|
|
b1533a3135 | ||
|
|
874d8fdac2 | ||
|
|
0e2e2876f4 | ||
|
|
e11ce95d95 | ||
|
|
7493f189a0 | ||
|
|
53fa66f120 | ||
|
|
519dd112ea | ||
|
|
414247d6c4 | ||
|
|
7ff2643d23 | ||
|
|
a0521f0260 | ||
|
|
6b07a0d9dc | ||
|
|
dc863c64c6 | ||
|
|
a8ffe91c79 | ||
|
|
fec7536617 | ||
|
|
e8c93359b1 | ||
|
|
04c37d12d2 | ||
|
|
9755728d43 | ||
|
|
37eed7c321 | ||
|
|
a6bfb61935 | ||
|
|
5abe2ccb26 | ||
|
|
e9347998b7 | ||
|
|
33299afbaa | ||
|
|
451e893d7d | ||
|
|
b67811ab3c | ||
|
|
09ea7e5f15 | ||
|
|
1c130c448c | ||
|
|
03dfabddbb | ||
|
|
d38fbc8e52 | ||
|
|
109e9555c8 | ||
|
|
1bf813068e | ||
|
|
aa2f7da029 | ||
|
|
0188b18d2b | ||
|
|
73bfc1cf48 | ||
|
|
3a7d6ca54b | ||
|
|
5d3c67b587 | ||
|
|
2458d51ed1 | ||
|
|
d4f1ae910c | ||
|
|
5abef94482 | ||
|
|
e14bef7ef3 | ||
|
|
98bdce156b | ||
|
|
dd6b3548f9 | ||
|
|
9e8bb474b4 | ||
|
|
9503884472 | ||
|
|
2383bcddcc | ||
|
|
b92d671c02 | ||
|
|
523d377a08 | ||
|
|
d5872aa851 | ||
|
|
283de0d29a | ||
|
|
ba210232ab | ||
|
|
b5693d7058 | ||
|
|
903ef4521b | ||
|
|
96e728901e | ||
|
|
6b07ea745c | ||
|
|
e64692ce9e | ||
|
|
9c46713a65 | ||
|
|
f6739f552d | ||
|
|
5d9a255b16 | ||
|
|
17144d4791 | ||
|
|
0284224787 | ||
|
|
fc41995a47 | ||
|
|
c94059fb85 | ||
|
|
69c517a8b2 | ||
|
|
dad99e85b2 | ||
|
|
8cb973d695 | ||
|
|
c680a90e49 | ||
|
|
1bf15599f7 | ||
|
|
727ca92afe | ||
|
|
e3c45dd1d0 | ||
|
|
ec58861e4e | ||
|
|
fb22dd81a4 | ||
|
|
1cba974c1d | ||
|
|
bf7d04f7a1 | ||
|
|
45a8096617 | ||
|
|
65f615d927 | ||
|
|
40a2f14600 | ||
|
|
7d55849900 | ||
|
|
450f380198 | ||
|
|
7cc144a9c3 | ||
|
|
6695f99c90 | ||
|
|
c6c36212f5 | ||
|
|
c384322d94 | ||
|
|
29cfdb01a0 | ||
|
|
e78cad1cbe | ||
|
|
0becbb8212 | ||
|
|
a9da258dcc | ||
|
|
1bde3d14bb | ||
|
|
8821053ff8 | ||
|
|
5c153ff74a | ||
|
|
0106a700c2 | ||
|
|
4639f8f7c6 | ||
|
|
bd4287762e | ||
|
|
ffbfe171c3 | ||
|
|
1bd59d9210 | ||
|
|
32a35f8653 | ||
|
|
0a3378eef8 | ||
|
|
dee8d7b0f7 | ||
|
|
fef2df8671 | ||
|
|
18759b0183 | ||
|
|
545aa114e8 | ||
|
|
889483d69c | ||
|
|
1668e23f80 | ||
|
|
c24bfb2e41 | ||
|
|
a03a294a12 | ||
|
|
a3e40a7471 | ||
|
|
5601be1276 | ||
|
|
6ceedcff0e | ||
|
|
74d6ac1183 | ||
|
|
0c601bbb8c | ||
|
|
578861b473 | ||
|
|
a5bad69e20 | ||
|
|
f41a1e394e | ||
|
|
1160a70960 | ||
|
|
7d73743a94 | ||
|
|
cd9095833a | ||
|
|
321bcfabd5 | ||
|
|
c01e2d46ec | ||
|
|
e857bff6af | ||
|
|
709543234f | ||
|
|
6eebeb8b57 | ||
|
|
71bda95ea6 | ||
|
|
81e22fd655 | ||
|
|
850b4e7ac6 | ||
|
|
82dca95473 | ||
|
|
330e874110 | ||
|
|
65051a63db | ||
|
|
498fa40613 | ||
|
|
011892025b | ||
|
|
3052b28fdc | ||
|
|
cc77ceb92a | ||
|
|
2880a632ff | ||
|
|
1a5c0d58e8 | ||
|
|
cc8a161fce | ||
|
|
ec4d5b7e6b | ||
|
|
7ddd8566f1 | ||
|
|
9796123462 | ||
|
|
ed5b6ee780 | ||
|
|
97a8be52d2 | ||
|
|
e1aff97fe2 | ||
|
|
efc3e713b1 | ||
|
|
1e5de6e01b | ||
|
|
962b425078 | ||
|
|
f065e8acdc | ||
|
|
738ec6de67 | ||
|
|
898b6e3479 | ||
|
|
72c0ee9e54 | ||
|
|
0776a479da | ||
|
|
a93ec92789 | ||
|
|
c0d5380017 | ||
|
|
fff84b844f | ||
|
|
2830c4eed5 | ||
|
|
a74661618e | ||
|
|
d562d44edf | ||
|
|
3b47c6550d | ||
|
|
de1173202d | ||
|
|
b62af81bde | ||
|
|
f88765ed7f | ||
|
|
3ddc5b47c8 | ||
|
|
719327d1ad | ||
|
|
5b2529602f | ||
|
|
f034f2058f | ||
|
|
e25afdd420 | ||
|
|
78796c4d95 | ||
|
|
c1528c53ff | ||
|
|
e96f8bacb1 | ||
|
|
5cef433c5a | ||
|
|
378e2c45ec | ||
|
|
5f1a3ee869 | ||
|
|
06bc072925 | ||
|
|
db23f1a1ca | ||
|
|
0747008037 | ||
|
|
8a9889c12c | ||
|
|
3d632fb90e | ||
|
|
45403e0909 | ||
|
|
5e55b80e2c | ||
|
|
545af8e735 | ||
|
|
f70e44a474 | ||
|
|
320284d03e | ||
|
|
e3bf541d88 | ||
|
|
12e85ae950 | ||
|
|
654f0e8e20 | ||
|
|
6d2cbd365f | ||
|
|
f94b6c7cdd | ||
|
|
07adbac96f | ||
|
|
810ff866a0 | ||
|
|
27eed22bdc | ||
|
|
965a7f0f12 | ||
|
|
528bacce7d | ||
|
|
80fadeb381 | ||
|
|
03cfbacafa | ||
|
|
2223b8ed9d | ||
|
|
8053275166 | ||
|
|
2e5dd7b5ef | ||
|
|
dcd717f83c | ||
|
|
5056d4a0f4 | ||
|
|
c198c2e453 | ||
|
|
bb8e185fbd | ||
|
|
c2a01e3aad | ||
|
|
8aa55eb010 | ||
|
|
99b01b0734 | ||
|
|
6a9ffd6842 | ||
|
|
5ad9d61fdc | ||
|
|
701276bc80 | ||
|
|
3445b75216 | ||
|
|
516734b18a | ||
|
|
fedfddf407 | ||
|
|
4bcf97353a | ||
|
|
2fa4a0458d | ||
|
|
bbee2b7433 | ||
|
|
a3c7b2dbb3 | ||
|
|
7130c10ef3 | ||
|
|
93d66a0f37 | ||
|
|
8b922127b8 | ||
|
|
8a3d8fea4d | ||
|
|
6077e7453c | ||
|
|
1959d79717 | ||
|
|
26bd26f998 | ||
|
|
c8a1f55657 | ||
|
|
7243c922ef | ||
|
|
2e912d233a | ||
|
|
1d55c4d300 | ||
|
|
29a56da565 | ||
|
|
4e0cd4038e | ||
|
|
4e5bef96a6 | ||
|
|
1fa8950571 | ||
|
|
6e87f6665b | ||
|
|
8989106e91 | ||
|
|
9a9443fe85 | ||
|
|
7fd5079973 | ||
|
|
b2cf7a965f | ||
|
|
8478b5daa1 | ||
|
|
331f78eb43 | ||
|
|
5deb863dd8 | ||
|
|
1cf3ff4863 | ||
|
|
9ae863ca3a | ||
|
|
0fc2a98e6e | ||
|
|
6f5f993ada | ||
|
|
1e7cfaf92d | ||
|
|
b41d0c1040 | ||
|
|
716922f76f | ||
|
|
573844ada4 | ||
|
|
cd7f8f91b6 | ||
|
|
fec4640b5a | ||
|
|
8504e29743 | ||
|
|
695f6a9e4f | ||
|
|
4838167696 | ||
|
|
f03429f47c | ||
|
|
97908ac6c1 | ||
|
|
3a3cba602c | ||
|
|
1c138efac2 | ||
|
|
07fd041efb | ||
|
|
da7849251d | ||
|
|
466c3c8c79 | ||
|
|
2142894cba | ||
|
|
76ff13b47e | ||
|
|
799f98339e | ||
|
|
d695d283f6 | ||
|
|
553c85b7ff | ||
|
|
6663fbeeed | ||
|
|
19e44f9b64 | ||
|
|
c93f50dc37 | ||
|
|
bb4cd1ebf5 | ||
|
|
e12966a4fd | ||
|
|
b350b355c0 | ||
|
|
9df3881128 | ||
|
|
557adfc327 | ||
|
|
97ad525d5b | ||
|
|
0fd02c5ecf | ||
|
|
27a77567dd | ||
|
|
57a615d6ce | ||
|
|
deb3247b99 | ||
|
|
b9adb507f8 | ||
|
|
c6fba8543f | ||
|
|
7c2cb14a80 | ||
|
|
b125f0681f | ||
|
|
20d16c5275 | ||
|
|
639e3657cd | ||
|
|
559b10e90a | ||
|
|
e63f1d542a | ||
|
|
51089765d0 | ||
|
|
54cced7c56 | ||
|
|
3d546693c6 | ||
|
|
40ced9997e | ||
|
|
3bd188122e | ||
|
|
9b5849f470 | ||
|
|
942cca8eef | ||
|
|
a9f39b85d5 | ||
|
|
15fc44be94 | ||
|
|
2eb1fe069c | ||
|
|
a82b6223aa | ||
|
|
433dea41e8 | ||
|
|
e26a009fc1 | ||
|
|
49a81c9c1f | ||
|
|
7e8179a704 | ||
|
|
d50d8d8900 | ||
|
|
243514ec17 | ||
|
|
be75d8fe95 | ||
|
|
bb8cefa33b | ||
|
|
0a44bbae9e | ||
|
|
fb387a16b6 | ||
|
|
e358cb6e6e | ||
|
|
341ebdf6cc | ||
|
|
6d2d6c38ec | ||
|
|
d27b7ef40a | ||
|
|
27bdda265f | ||
|
|
7d59a83c18 | ||
|
|
9d472290f2 | ||
|
|
e29d961be3 | ||
|
|
809d32c4d8 | ||
|
|
046f46ce8d | ||
|
|
51dd107767 | ||
|
|
d9e406ca99 | ||
|
|
a2bdbc8b56 | ||
|
|
743899055a | ||
|
|
f6ffd125c9 | ||
|
|
f3693ef112 | ||
|
|
a87163fb14 | ||
|
|
2649fa0aab | ||
|
|
12cec14b56 | ||
|
|
44ae3a8ab5 | ||
|
|
a3a271aad5 | ||
|
|
9041ee8df9 | ||
|
|
052636ff0f | ||
|
|
c8805265e2 | ||
|
|
a28ddc8285 | ||
|
|
0245a2197b | ||
|
|
bf3b5c5e1f | ||
|
|
76ffc82bba | ||
|
|
3893be6ed1 | ||
|
|
a82aeef2eb | ||
|
|
e13b86950a | ||
|
|
2f9d9c582c | ||
|
|
d731cb4c0f | ||
|
|
fec92d2f22 | ||
|
|
00dd4f1b7f | ||
|
|
e7f850c2aa | ||
|
|
85e63ca252 | ||
|
|
5accb6056b | ||
|
|
4734c57f2b | ||
|
|
fcde95750b | ||
|
|
eab58b8190 | ||
|
|
48e40a385c | ||
|
|
4d511a3a42 | ||
|
|
a53eb44083 | ||
|
|
ea1a1dd5e2 | ||
|
|
ff5bcdee3f | ||
|
|
559706696a | ||
|
|
02aea2e65e | ||
|
|
8c3ef60da1 | ||
|
|
b5b6a4ee26 | ||
|
|
e992f952d3 | ||
|
|
e5105ab33f | ||
|
|
44c51e88ca | ||
|
|
bb028a569f | ||
|
|
e4faa179b6 | ||
|
|
9efc71d42e | ||
|
|
415900ab01 | ||
|
|
50be30e5db | ||
|
|
95f29d0440 | ||
|
|
ee478ed6a5 | ||
|
|
e53c77e2be | ||
|
|
6f838a2131 | ||
|
|
e4dfada264 | ||
|
|
bce52eec38 | ||
|
|
2683b2db6f | ||
|
|
08bb6fe003 | ||
|
|
7de9ade8aa | ||
|
|
f714b22dc4 | ||
|
|
0fd05d3f5c | ||
|
|
85be8e726b | ||
|
|
eee040d066 | ||
|
|
364d090667 | ||
|
|
04a924f716 | ||
|
|
c2ceb923e4 | ||
|
|
11449b5943 | ||
|
|
b6a4a66aef | ||
|
|
95544b65ef | ||
|
|
407bb2bc70 | ||
|
|
4b98022688 | ||
|
|
1f51bad9d1 | ||
|
|
8f51a4318a | ||
|
|
3b42c6250d | ||
|
|
6343f7e861 | ||
|
|
7498e8f848 | ||
|
|
e49959b833 | ||
|
|
f31e50381f | ||
|
|
0b373817a8 | ||
|
|
93fb9cbf6c | ||
|
|
e599fa57aa | ||
|
|
00ec9a8898 | ||
|
|
22485957fe | ||
|
|
06c7d6d7af | ||
|
|
858f03fde4 | ||
|
|
ea29a5d1a4 | ||
|
|
012d817288 | ||
|
|
ab7cf4655a | ||
|
|
9318001dcc | ||
|
|
a7b57ccfc2 | ||
|
|
6300c99924 | ||
|
|
701aa28b22 | ||
|
|
b9a945c5b9 | ||
|
|
a06ad04701 | ||
|
|
ca3757152f | ||
|
|
c23a439332 | ||
|
|
0a4741e4df | ||
|
|
a3951098c6 | ||
|
|
868d61a839 | ||
|
|
8cb4465e8a | ||
|
|
de5257ece9 | ||
|
|
29d004b22d | ||
|
|
716287cb2e | ||
|
|
3e9b54eb0d | ||
|
|
261540ad42 | ||
|
|
5abfaabae6 | ||
|
|
c1278f4b99 | ||
|
|
b486a72021 | ||
|
|
5c4a6603b9 | ||
|
|
ef203cb2db | ||
|
|
c361da5c9d | ||
|
|
ca6ef15294 | ||
|
|
435b446a6a | ||
|
|
f4120ad602 | ||
|
|
5e27a7023a | ||
|
|
8cd085914a | ||
|
|
a4629d5fb4 | ||
|
|
3b791e2e61 | ||
|
|
7c70c67e30 | ||
|
|
28b543bc0c | ||
|
|
99d80f30a9 | ||
|
|
17ec90892a | ||
|
|
95de5c29d6 | ||
|
|
cadd02ce29 | ||
|
|
1011519e19 | ||
|
|
3df5eb92b2 | ||
|
|
1ea634e6e3 | ||
|
|
5b1b84aeaa | ||
|
|
06365d9739 | ||
|
|
fab1986fb6 | ||
|
|
bc6862ef5d | ||
|
|
dbc8a21085 | ||
|
|
979167599b | ||
|
|
cba59be0ee | ||
|
|
ef62181549 | ||
|
|
afda0e45e5 | ||
|
|
346cfab35d | ||
|
|
b36944e563 | ||
|
|
579dec2f52 | ||
|
|
e84cfc28fc | ||
|
|
c582d8c9ad | ||
|
|
f7c4fcd0f1 | ||
|
|
fd8948575a | ||
|
|
90be6089a5 | ||
|
|
57d1cbc739 | ||
|
|
81fd00043e | ||
|
|
e27901b224 | ||
|
|
9ac5ed9274 | ||
|
|
49aacef240 | ||
|
|
46daf3f065 | ||
|
|
996c3b1ead | ||
|
|
42987b038b | ||
|
|
bb715fa4d4 | ||
|
|
50af682579 | ||
|
|
84607766c3 | ||
|
|
980ce494db | ||
|
|
0d132c0309 | ||
|
|
363a047b21 | ||
|
|
f3f14e4a04 | ||
|
|
a370bce5b9 | ||
|
|
faf3ff1959 | ||
|
|
76a14b550f | ||
|
|
89353aa7c8 | ||
|
|
2ead0cafd2 | ||
|
|
92e6c8f3ff | ||
|
|
5cb2b2e089 | ||
|
|
600640bb35 | ||
|
|
7db40eece4 | ||
|
|
9341a82b87 | ||
|
|
836cb980f2 | ||
|
|
42dfc8b04f | ||
|
|
63b4957b0f | ||
|
|
490eb5882b | ||
|
|
c21ce5d285 | ||
|
|
d163c8ed29 | ||
|
|
3c0d70987d | ||
|
|
6e0045bd87 | ||
|
|
40efa88989 | ||
|
|
61eed98f07 | ||
|
|
2232ae1e57 | ||
|
|
235726e8a9 | ||
|
|
84b96f6f8c | ||
|
|
35766b37d7 | ||
|
|
0013836384 | ||
|
|
f1208cfa32 | ||
|
|
159785a3b5 | ||
|
|
283580d2a4 | ||
|
|
c270e72a14 | ||
|
|
52ab8d3797 | ||
|
|
37f99ce186 | ||
|
|
77fd4fca69 | ||
|
|
fbbb03e5c7 | ||
|
|
5f88cc686c | ||
|
|
2b0d61acf5 |
No files matched your search
@@ -0,0 +1,153 @@
|
||||
---
|
||||
name: bumping-reva
|
||||
description: Use when the user asks to bump, update, or upgrade the OpenCloud reva dependency to a specific version (e.g. "reva bump to 2.48.0", "bump reva to v2.48.0"). Covers editing go.mod, re-vendoring, bumping the OpenCloud LatestTag, the single commit, and opening the PR against main.
|
||||
---
|
||||
|
||||
# Bumping Reva
|
||||
|
||||
## Overview
|
||||
|
||||
Bumping reva updates the pinned [opencloud-eu/reva](https://github.com/opencloud-eu/reva) dependency (`github.com/opencloud-eu/reva/v2`) to a tagged release, re-vendors the module graph, and bumps the OpenCloud dev version. It touches `go.mod`, `go.sum`, `vendor/**` and `pkg/version/version.go`, lands as one commit, and ships as a PR whose body is the reva changelog for that version.
|
||||
|
||||
Template PR: https://github.com/opencloud-eu/opencloud/pull/3127
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- **The reva release must already be tagged.** A reva release is cut by merging its release PR (title `🎉 Release X.Y.Z`, branch `next-release/main`). The **user merges that PR themselves** — this skill starts *after* the tag `vX.Y.Z` exists. Verify the tag before doing anything (step 1); if it's missing, stop and ask the user to merge the reva release PR first.
|
||||
- **`gh` (GitHub CLI), authenticated** — tag lookup and PR creation go through `gh api` / `gh pr`. Verify with `gh auth status`; if it fails, ask the user to run `gh auth login` (suggest `! gh auth login` so it runs in-session).
|
||||
- `gh` needs the system keyring, so run all `gh` commands with the sandbox disabled.
|
||||
- **Go toolchain + network** — `go get` / `go mod tidy` / `go mod vendor` hit the Go module proxy. Run them with the sandbox disabled (network access).
|
||||
- `git` and `base64` (decoding the changelog) — standard on macOS/Linux.
|
||||
|
||||
## Inputs
|
||||
|
||||
- `REVA_VERSION` — the new reva tag, always normalized to a leading `v` (e.g. `v2.48.0`). If the user didn't give it, ask (or take the latest reva release tag).
|
||||
- `OC_VERSION` — the OpenCloud target for `LatestTag`, **without** the `+dev` suffix (e.g. `7.4.0`). **Do not ask or guess** — derive it from the open OpenCloud release PR (step 3). It can be a new major (e.g. `8.0.0`) when release-please picked up a breaking change.
|
||||
|
||||
## What changes
|
||||
|
||||
| File | What |
|
||||
| ------------------------ | ------------------------------------------------------------------- |
|
||||
| `go.mod` | `github.com/opencloud-eu/reva/v2` → `REVA_VERSION` (+ indirect deps pulled by `go mod tidy`) |
|
||||
| `go.sum` | updated by `go get` / `go mod tidy` |
|
||||
| `vendor/**` | re-vendored by `go mod vendor` (incl. `vendor/modules.txt`) |
|
||||
| `pkg/version/version.go` | `LatestTag = "<OC_VERSION>+dev"` |
|
||||
|
||||
## Procedure
|
||||
|
||||
### 1. Verify the reva tag exists
|
||||
|
||||
```bash
|
||||
gh api repos/opencloud-eu/reva/commits/$REVA_VERSION --jq '.sha'
|
||||
```
|
||||
|
||||
- Success (a sha) → the release is tagged, continue.
|
||||
- `422`/`404` → the tag does not exist yet. The reva release PR (`🎉 Release X.Y.Z`) is probably not merged. **Stop** and tell the user to merge it first. Helpful checks:
|
||||
```bash
|
||||
gh api repos/opencloud-eu/reva/releases/latest --jq '.tag_name' # current latest tag
|
||||
gh pr list --repo opencloud-eu/reva --search '🎉 Release in:title' --state open --json number,title
|
||||
```
|
||||
|
||||
### 2. Bump the dependency and re-vendor
|
||||
|
||||
```bash
|
||||
go get github.com/opencloud-eu/reva/v2@$REVA_VERSION
|
||||
go mod tidy
|
||||
go mod vendor
|
||||
```
|
||||
|
||||
(Sandbox disabled — these need network.) Notes:
|
||||
- Right after a fresh tag the module proxy can lag; if `go get` reports the version as unknown, retry, or use `GOPROXY=direct go get github.com/opencloud-eu/reva/v2@$REVA_VERSION`.
|
||||
- `go mod tidy` will also bump indirect dependencies that reva pulled in — that is expected (the template PR did the same).
|
||||
|
||||
### 3. Bump the OpenCloud dev version
|
||||
|
||||
`OC_VERSION` is the version of the **open OpenCloud release PR** — the release-please PR from branch `next-release/main`, titled `🎉 Release X.Y.Z` (e.g. #3143). Derive it, don't ask:
|
||||
|
||||
```bash
|
||||
gh pr list --repo opencloud-eu/opencloud --head next-release/main --state open \
|
||||
--json title --jq '.[0].title' | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1
|
||||
```
|
||||
|
||||
This is the next release target and tracks breaking changes — it may be a new major (e.g. `8.0.0`), not just a minor bump. If no such PR is open, stop and ask the user.
|
||||
|
||||
Edit `pkg/version/version.go`:
|
||||
|
||||
```go
|
||||
LatestTag = "<OC_VERSION>+dev" // e.g. "7.4.0+dev"
|
||||
```
|
||||
|
||||
### 4. Fetch the reva changelog for the PR body
|
||||
|
||||
```bash
|
||||
gh api "repos/opencloud-eu/reva/contents/CHANGELOG.md?ref=$REVA_VERSION" --jq '.content' | base64 -d
|
||||
```
|
||||
|
||||
Take **only the section for this version** and trim it exactly like the web bump: start at the first content heading (`### 🐛 Bug Fixes` / `### 📈 Enhancement` / `### 💥 Breaking changes`), drop the `# Changelog` title, the `## [x.y.z] - date` header and the `### ❤️ Thanks to all contributors!` block, and stop before the next `## [...]` version header.
|
||||
|
||||
Then **prepend two summary bullets** so the final PR body is:
|
||||
|
||||
```
|
||||
- bump opencloud version to <OC_VERSION>
|
||||
- reva bump <REVA_VERSION without the leading v>
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
...trimmed reva changelog...
|
||||
```
|
||||
|
||||
Write this to a file for `--body-file` (e.g. in the scratchpad).
|
||||
|
||||
### 5. Confirm before committing
|
||||
|
||||
The `vendor/` diff is huge — do **not** dump it. Show the user:
|
||||
|
||||
```bash
|
||||
git diff go.mod pkg/version/version.go # the meaningful edits
|
||||
git diff --stat | tail -1 # vendor churn summary
|
||||
```
|
||||
|
||||
Confirm the reva line in `go.mod` is exactly `github.com/opencloud-eu/reva/v2 REVA_VERSION`, show the target branch (`main`), and the PR body. **Do not commit until the user approves.**
|
||||
|
||||
### 6. Commit, push, open PR
|
||||
|
||||
- Create a branch (do not commit on `main`), e.g. `reva-bump-2.48.0`.
|
||||
- Stage everything the bump touched: `git add go.mod go.sum vendor pkg/version/version.go`.
|
||||
- One commit, conventional-commits format, **empty body**:
|
||||
```
|
||||
chore: bump reva to 2.48.0
|
||||
```
|
||||
- PR base: **`main`** (reva bumps always target main).
|
||||
- PR title: `[full-ci] chore: bump reva to 2.48.0` (the commit message prefixed with `[full-ci] `).
|
||||
- PR body: the file from step 4.
|
||||
- Add the label `Type:Maintenance`.
|
||||
|
||||
```bash
|
||||
gh pr create --base main \
|
||||
--title "[full-ci] chore: bump reva to $REVA_VERSION_NO_V" \
|
||||
--label "Type:Maintenance" \
|
||||
--body-file <body-file>
|
||||
```
|
||||
|
||||
(`gh` commands need the sandbox disabled — they require the system keyring.)
|
||||
|
||||
## Quick reference
|
||||
|
||||
```bash
|
||||
REVA_VERSION=v2.48.0
|
||||
gh api repos/opencloud-eu/reva/commits/$REVA_VERSION --jq '.sha' # verify tag exists
|
||||
OC_VERSION=$(gh pr list --repo opencloud-eu/opencloud --head next-release/main --state open \
|
||||
--json title --jq '.[0].title' | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1) # from open release PR
|
||||
go get github.com/opencloud-eu/reva/v2@$REVA_VERSION && go mod tidy && go mod vendor # bump + re-vendor
|
||||
# edit pkg/version/version.go -> LatestTag = "$OC_VERSION+dev"
|
||||
gh api "repos/opencloud-eu/reva/contents/CHANGELOG.md?ref=$REVA_VERSION" --jq '.content' | base64 -d # changelog
|
||||
```
|
||||
|
||||
## Common mistakes
|
||||
|
||||
- Running the bump before the reva release PR is merged — the tag won't exist and `go get` will fail. Verify the tag first (step 1).
|
||||
- Forgetting to re-run `go mod vendor` after `go mod tidy`, leaving `vendor/` out of sync with `go.mod`.
|
||||
- Asking for or hardcoding `OC_VERSION` — always derive it from the open `next-release/main` release PR (step 3); it can even be a new major after a breaking change.
|
||||
- Reading the changelog from reva `main` instead of the tag (`?ref=$REVA_VERSION`). Always pin to the tag.
|
||||
- Missing the `[full-ci] ` prefix in the PR title, the `Type:Maintenance` label, or the two summary bullets at the top of the body.
|
||||
- Dumping the full `vendor/` diff at the confirmation step instead of `go.mod` + `version.go` + a `--stat` summary.
|
||||
- Committing before the user confirms the diff.
|
||||
@@ -0,0 +1,118 @@
|
||||
---
|
||||
name: bumping-web
|
||||
description: Use when the user asks to bump, update, or upgrade the OpenCloud web assets/frontend to a specific version (e.g. "bump web to v7.0.0", "update web to v7.1.2"). Covers editing the version files, the single commit, and opening the PR against the right branch.
|
||||
---
|
||||
|
||||
# Bumping Web
|
||||
|
||||
## Overview
|
||||
|
||||
Bumping web updates the pinned OpenCloud web frontend (assets + UI-test runner) to a tagged release of [opencloud-eu/web](https://github.com/opencloud-eu/web). It touches exactly two files, lands as one commit, and ships as a PR whose body is the web changelog for that version.
|
||||
|
||||
Template PR: https://github.com/opencloud-eu/opencloud/pull/2733
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- **`gh` (GitHub CLI), authenticated** — every lookup and the PR creation go through `gh api` / `gh pr`. Verify with `gh auth status`; if it fails, ask the user to run `gh auth login` (suggest `! gh auth login` so it runs in-session). Do not proceed without it.
|
||||
- `gh` needs the system keyring, so run all `gh` commands with the sandbox disabled.
|
||||
- `git` and `base64` (decoding the changelog) — standard on macOS/Linux.
|
||||
|
||||
## What changes (exactly two files)
|
||||
|
||||
| File | Variable | New value |
|
||||
| ----------------------- | -------------------- | ------------------------------------------------ |
|
||||
| `services/web/Makefile` | `WEB_ASSETS_VERSION` | the version tag, e.g. `v7.0.0` |
|
||||
| `services/web/Makefile` | `WEB_ASSETS_BRANCH` | branch carrying the tag (`main` or `stable-X.Y`) |
|
||||
| `.woodpecker.env` | `WEB_COMMITID` | full commit sha the tag points to |
|
||||
| `.woodpecker.env` | `WEB_BRANCH` | same branch as `WEB_ASSETS_BRANCH` |
|
||||
|
||||
`WEB_ASSETS_BRANCH` and `WEB_BRANCH` are always the same value.
|
||||
|
||||
## Procedure
|
||||
|
||||
Let `VERSION` be the requested tag (always normalize to a leading `v`, e.g. `v7.0.0`).
|
||||
|
||||
### 1. Resolve the commit sha the tag points to
|
||||
|
||||
```bash
|
||||
gh api repos/opencloud-eu/web/commits/$VERSION --jq '.sha'
|
||||
```
|
||||
|
||||
This full sha is the new `WEB_COMMITID`.
|
||||
|
||||
### 2. Determine the branch (`main` vs `stable-X.Y`)
|
||||
|
||||
The branch is the line of development that carries the tag. Detect it:
|
||||
|
||||
```bash
|
||||
gh api "repos/opencloud-eu/web/compare/main...$VERSION" --jq '.status'
|
||||
```
|
||||
|
||||
- `identical` or `behind` → the tagged commit is reachable from `main` → use **`main`**.
|
||||
- `ahead` or `diverged` → the tag lives on a release line → use **`stable-X.Y`** matching the version's major.minor (e.g. `v7.1.2` → `stable-7.1`).
|
||||
|
||||
Sanity-check that the stable branch actually exists:
|
||||
|
||||
```bash
|
||||
gh api repos/opencloud-eu/web/branches --paginate --jq '.[].name' | grep -E 'main|stable'
|
||||
```
|
||||
|
||||
Typically a freshly released minor (`v7.1.0`) still sits on `main`, while later patches on an older line (`v7.0.3` after `7.1` exists) sit on `stable-7.0`.
|
||||
|
||||
### 3. Fetch the changelog for the PR body
|
||||
|
||||
```bash
|
||||
gh api "repos/opencloud-eu/web/contents/CHANGELOG.md?ref=$VERSION" --jq '.content' | base64 -d
|
||||
```
|
||||
|
||||
Take **only the section for this version**. Match the template: start the PR body at the first content heading (e.g. `### 💥 Breaking changes` / `### 📈 Enhancement`) and drop the `# Changelog` title, the `## [x.y.z] - date` header, and the `### ❤️ Thanks to all contributors!` block. Stop before the next `## [...]` version header.
|
||||
|
||||
### 4. Apply the edits
|
||||
|
||||
Edit `services/web/Makefile` (`WEB_ASSETS_VERSION`, `WEB_ASSETS_BRANCH`) and `.woodpecker.env` (`WEB_COMMITID`, `WEB_BRANCH`).
|
||||
|
||||
### 5. Pick the target branch for the PR
|
||||
|
||||
- Major or minor release → target **`main`**.
|
||||
- Patch release → may need to target a stable branch instead. If the user did not specify, **ask them** which branch to target before continuing.
|
||||
|
||||
### 6. Confirm before committing
|
||||
|
||||
Show the user the diff of both files and the target branch, and ask them to confirm. Do not commit until they approve.
|
||||
|
||||
### 7. Commit, push, open PR
|
||||
|
||||
- Create a branch (do not commit on `main`).
|
||||
- One commit, conventional-commits format, **empty body**:
|
||||
```
|
||||
chore: bump web to v7.0.0
|
||||
```
|
||||
- PR title: `[full-ci] chore: bump web to v7.0.0` (the commit message prefixed with `[full-ci] `).
|
||||
- PR base: the branch chosen in step 5.
|
||||
- PR body: the trimmed changelog from step 3.
|
||||
- Add the label `Type:Dependencies`.
|
||||
|
||||
```bash
|
||||
gh pr create --base <target-branch> \
|
||||
--title "[full-ci] chore: bump web to $VERSION" \
|
||||
--label "Type:Dependencies" \
|
||||
--body-file <changelog-file>
|
||||
```
|
||||
|
||||
(`gh` commands need the sandbox disabled — they require the system keyring.)
|
||||
|
||||
## Quick reference
|
||||
|
||||
```bash
|
||||
VERSION=v7.0.0
|
||||
gh api repos/opencloud-eu/web/commits/$VERSION --jq '.sha' # WEB_COMMITID
|
||||
gh api "repos/opencloud-eu/web/compare/main...$VERSION" --jq '.status' # main vs stable
|
||||
gh api "repos/opencloud-eu/web/contents/CHANGELOG.md?ref=$VERSION" --jq '.content' | base64 -d # changelog
|
||||
```
|
||||
|
||||
## Common mistakes
|
||||
|
||||
- Reading `WEB_COMMITID` or the changelog from web `main` instead of from the version tag (`?ref=$VERSION`). Always pin to the tag.
|
||||
- Leaving `WEB_ASSETS_BRANCH`/`WEB_BRANCH` on `main` for a patch that belongs on a stable line.
|
||||
- Forgetting `[full-ci] ` in the PR title or adding a commit body.
|
||||
- Committing before the user confirms the diff and target branch.
|
||||
@@ -65,6 +65,12 @@ $(GOVULNCHECK): $(BINGO_DIR)/govulncheck.mod
|
||||
@echo "(re)installing $(GOBIN)/govulncheck-v1.1.4"
|
||||
@cd $(BINGO_DIR) && GOWORK=off $(GO) build -mod=mod -modfile=govulncheck.mod -o=$(GOBIN)/govulncheck-v1.1.4 "golang.org/x/vuln/cmd/govulncheck"
|
||||
|
||||
GOWRAP := $(GOBIN)/gowrap-v1.4.3
|
||||
$(GOWRAP): $(BINGO_DIR)/gowrap.mod
|
||||
@# Install binary/ries using Go 1.14+ build command. This is using bwplotka/bingo-controlled, separate go module with pinned dependencies.
|
||||
@echo "(re)installing $(GOBIN)/gowrap-v1.4.3"
|
||||
@cd $(BINGO_DIR) && GOWORK=off $(GO) build -mod=mod -modfile=gowrap.mod -o=$(GOBIN)/gowrap-v1.4.3 "github.com/hexdigest/gowrap/cmd/gowrap"
|
||||
|
||||
MOCKERY := $(GOBIN)/mockery-v3.4.0
|
||||
$(MOCKERY): $(BINGO_DIR)/mockery.mod
|
||||
@# Install binary/ries using Go 1.14+ build command. This is using bwplotka/bingo-controlled, separate go module with pinned dependencies.
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
module _ // Auto generated by https://github.com/bwplotka/bingo. DO NOT EDIT
|
||||
|
||||
go 1.25.8
|
||||
|
||||
require github.com/hexdigest/gowrap v1.4.3 // cmd/gowrap
|
||||
@@ -0,0 +1,55 @@
|
||||
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
|
||||
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
||||
github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
|
||||
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
|
||||
github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8=
|
||||
github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/hexdigest/gowrap v1.4.3 h1:m+t8aj1pUiFQbEiE8QJg2xdYVH5DAMluLgZ9P/qEF0k=
|
||||
github.com/hexdigest/gowrap v1.4.3/go.mod h1:XWL8oQW2H3fX5ll8oT3Fduh4mt2H3cUAGQHQLMUbmG4=
|
||||
github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw=
|
||||
github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
|
||||
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
|
||||
github.com/mitchellh/copystructure v1.1.2 h1:Th2TIvG1+6ma3e/0/bopBKohOTY7s4dA8V2q4EUcBJ0=
|
||||
github.com/mitchellh/copystructure v1.1.2/go.mod h1:EBArHfARyrSWO/+Wyr9zwEkc6XMFB9XyNgFNmRkZZU4=
|
||||
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/mitchellh/reflectwalk v1.0.1 h1:FVzMWA5RllMAKIdUSC8mdWo3XtwoecrH79BY70sEEpE=
|
||||
github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
|
||||
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA=
|
||||
github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
|
||||
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
|
||||
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
|
||||
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
||||
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
||||
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
|
||||
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
@@ -24,6 +24,8 @@ GOLANGCI_LINT="${GOBIN}/golangci-lint-v1.64.6"
|
||||
|
||||
GOVULNCHECK="${GOBIN}/govulncheck-v1.1.4"
|
||||
|
||||
GOWRAP="${GOBIN}/gowrap-v1.4.3"
|
||||
|
||||
MOCKERY="${GOBIN}/mockery-v3.4.0"
|
||||
|
||||
MUTAGEN="${GOBIN}/mutagen-v0.18.1"
|
||||
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../.agents/skills
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
exclude_paths:
|
||||
- '.github/**'
|
||||
- '.agents/**'
|
||||
- 'CHANGELOG.md'
|
||||
- '**/CHANGELOG.md'
|
||||
- 'changelog/**'
|
||||
@@ -15,7 +16,10 @@ exclude_paths:
|
||||
- 'idp/src/**'
|
||||
- 'devtools/**'
|
||||
- 'deployments/**'
|
||||
- "release-config.ts"
|
||||
- 'tests/acceptance/expected-failures-*.md'
|
||||
# written by the search engine parity suite, table rows are as wide as they are
|
||||
- 'services/search/pkg/parity/README.md'
|
||||
- 'tests/acceptance/bootstrap/**'
|
||||
- 'tests/acceptance/TestHelpers/**'
|
||||
- 'tests/acceptance/scripts/run.sh'
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
github: opencloud-eu
|
||||
@@ -0,0 +1,32 @@
|
||||
### Rolling release template
|
||||
[Release Template](https://github.com/opencloud-eu/opencloud/blob/main/.github/rolling_release_template.md)
|
||||
|
||||
## Prerequisites
|
||||
* [ ] replace `%%NEXT%%` with the release version
|
||||
|
||||
* [ ] web release
|
||||
* [ ] bump web version
|
||||
* [ ] squash and merge the web release PR
|
||||
* [ ] bump web v.x.y.z in opencloud
|
||||
|
||||
* [ ] reva release
|
||||
* [ ] squash and merge the reva Release PR
|
||||
* [ ] bump reva and update opencloud version in `pkg/version.go`
|
||||
|
||||
## QA Phase
|
||||
* [ ] bump `opencloud_commitid` in web and run all working tests in CI
|
||||
* [ ] compatibility test
|
||||
* [ ] confirmatory testing, if needed
|
||||
* [ ] squash and merge Release PR
|
||||
|
||||
## Collected bugs
|
||||
|
||||
## After QA Phase
|
||||
* [ ] publish release notes to the docs
|
||||
* [ ] add migration guide to changelog with prefix `**ACTION REQUIRED:**`, if needed.
|
||||
* [ ] add release notes from web and reva to opencloud changelog
|
||||
* [ ] n8n integration - update new opencloud version
|
||||
* [ ] docker-compose - update new opencloud version
|
||||
* [ ] update the public matrix channel topic
|
||||
* [ ] update https://update.opencloud.eu/server.json
|
||||
* [ ] update the version on demo.opencloud.eu
|
||||
@@ -1,4 +1,2 @@
|
||||
_extends: gh-labels
|
||||
|
||||
|
||||
|
||||
+3
-4
@@ -36,12 +36,11 @@ vendor-bin/**/composer.lock
|
||||
vendor-php
|
||||
|
||||
# API acceptance tests - auto-generated files
|
||||
.php-cs-fixer.cache
|
||||
suite-logs
|
||||
tests/acceptance/filesForUpload/filesWithVirus/
|
||||
|
||||
# QA activity reports
|
||||
tests/qa-activity-report/reports/
|
||||
# Generated docs page (published to the server-testing-docs branch by CI)
|
||||
tests/.docs-dist/
|
||||
|
||||
# drone CI is in .drone.star, do not let someone accidentally commit a local .drone.yml
|
||||
.drone.yml
|
||||
@@ -65,4 +64,4 @@ go.work.sum
|
||||
.DS_Store
|
||||
|
||||
# example deployments
|
||||
**/opencloud-sandbox-*
|
||||
**/opencloud-sandbox-*
|
||||
Executable
+21
@@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
# Purpose of this script is to parse the go.mod file to retrieve the version of
|
||||
# Go that we are using, either from a "toolchain" directive (preferred), or from
|
||||
# a "go" directive as a fallback.
|
||||
#
|
||||
# The script then outputs that version, where it will be picked up as an environment
|
||||
# variable in mise.
|
||||
|
||||
F="./go.mod"
|
||||
|
||||
AWK=awk
|
||||
# prefer 'gawk' over 'awk' to make sure we get GNU awk
|
||||
command -v gawk &>/dev/null && AWK=gawk
|
||||
|
||||
[[ -e $F ]] || { echo "ERROR: failed to find $F" >&2; exit 1;}
|
||||
|
||||
GO_VERSION=$("$AWK" '/^toolchain/ {print $2; exit} /^go / {print $2}' "$F")
|
||||
GO_VERSION=${GO_VERSION#go} # strip the potential 'go' prefix:
|
||||
echo "${GO_VERSION}"
|
||||
@@ -1,31 +0,0 @@
|
||||
<?php
|
||||
|
||||
$dirToParse = 'tests/acceptance/';
|
||||
$dirIterator = new DirectoryIterator(__DIR__ . '/' . $dirToParse);
|
||||
|
||||
$excludeDirs = [
|
||||
'node_modules',
|
||||
'vendor-php'
|
||||
];
|
||||
|
||||
$finder = PhpCsFixer\Finder::create()
|
||||
->exclude($excludeDirs)
|
||||
->in(__DIR__);
|
||||
|
||||
$ocRule = (new OC\CodingStandard\Config())->getRules();
|
||||
$config = new PhpCsFixer\Config();
|
||||
$config->setFinder($finder)
|
||||
->setIndent("\t")
|
||||
->setRules(
|
||||
array_merge(
|
||||
$ocRule,
|
||||
[
|
||||
"return_type_declaration" => [
|
||||
"space_before" => "none",
|
||||
],
|
||||
'single_space_around_construct' => true
|
||||
]
|
||||
)
|
||||
);
|
||||
$config->setFinder($finder);
|
||||
return $config;
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"alexkrechik.cucumberautocomplete"
|
||||
]
|
||||
}
|
||||
Vendored
+16
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"cucumberautocomplete.steps": [
|
||||
"tests/acceptance/bootstrap/*.php"
|
||||
],
|
||||
"cucumberautocomplete.syncfeatures": "tests/acceptance/features/**/*.feature",
|
||||
"cucumberautocomplete.strictGherkinCompletion": false,
|
||||
"cucumberautocomplete.strictGherkinValidation": false,
|
||||
"cucumberautocomplete.customParameters": [
|
||||
{ "parameter": ":string", "value": "\"([^\"]*)\"" },
|
||||
{ "parameter": "'/\\^(.*)\\$/'", "value": "'^$1$$'", "isRegex": true, "flags": "g" },
|
||||
{ "parameter": "\\$\\w+", "value": "(.*)", "isRegex": true, "flags": "g" },
|
||||
{ "parameter": "(?<!\\?):[a-zA-Z_][a-zA-Z0-9_]*", "value": "\"([^\"]*)\"", "isRegex": true, "flags": "g" }
|
||||
],
|
||||
"cucumberautocomplete.gherkinDefinitionPart": "(Given|When|Then|But)\\(",
|
||||
"cucumberautocomplete.pureTextSteps": false
|
||||
}
|
||||
+2
-3
@@ -1,4 +1,3 @@
|
||||
# The test runner source for UI tests
|
||||
WEB_COMMITID=52b146f5356211e618ae26bfe39aed2feeec2d27
|
||||
WEB_BRANCH=stable-7.1
|
||||
|
||||
WEB_COMMITID=dffb3808702dab198065faa7a8aa16228e048385
|
||||
WEB_BRANCH=main
|
||||
+534
-317
File diff suppressed because it is too large.
Load diff
+198
@@ -1,5 +1,203 @@
|
||||
# Changelog
|
||||
|
||||
## [7.5.0](https://github.com/opencloud-eu/opencloud/releases/tag/v7.5.0) - 2026-08-25
|
||||
|
||||
### ❤️ Thanks to all contributors! ❤️
|
||||
|
||||
@AlexAndBear, @JammingBen, @Svanvith, @aduffeck, @butonic, @fschade, @junkerderprovinz, @kulmann, @maki5, @pbleser-oc, @rhafer, @saw-jan, @schweigisito, @v-scharf
|
||||
|
||||
### ✅ Tests
|
||||
|
||||
- test(api): update php test dependencies [[#3335](https://github.com/opencloud-eu/opencloud/pull/3335)]
|
||||
- fix(acceptance): fix running acceptance tests against host on Linux [[#3358](https://github.com/opencloud-eu/opencloud/pull/3358)]
|
||||
- fix(graph): adding the same user as multiple members in a group (#3354) [[#3356](https://github.com/opencloud-eu/opencloud/pull/3356)]
|
||||
- test(api): fix share role update test scenario [[#3322](https://github.com/opencloud-eu/opencloud/pull/3322)]
|
||||
- test: add api tests for cross-space search index mutation [[#3320](https://github.com/opencloud-eu/opencloud/pull/3320)]
|
||||
- ci: run search acceptance tests against OpenSearch in nightly [[#3302](https://github.com/opencloud-eu/opencloud/pull/3302)]
|
||||
- api-test: notification settings and getting email notifications [[#3281](https://github.com/opencloud-eu/opencloud/pull/3281)]
|
||||
- api-test: add posixfs scan and consistency CLI tests [[#3263](https://github.com/opencloud-eu/opencloud/pull/3263)]
|
||||
- api-test: replace sleeps with WaitHelper poll for async state [[#3239](https://github.com/opencloud-eu/opencloud/pull/3239)]
|
||||
|
||||
### 📈 Enhancement
|
||||
|
||||
- feat(thumbnails): extend list of default resolutions [[#3386](https://github.com/opencloud-eu/opencloud/pull/3386)]
|
||||
- ability to disable grpc and/or event consumer for event history service [[#3279](https://github.com/opencloud-eu/opencloud/pull/3279)]
|
||||
- feat(graph): add LibreGraphContentType on drive [[#3355](https://github.com/opencloud-eu/opencloud/pull/3355)]
|
||||
- feat: update space template image [[#3324](https://github.com/opencloud-eu/opencloud/pull/3324)]
|
||||
- feat(web): add rclone-crypt to default apps [[#3313](https://github.com/opencloud-eu/opencloud/pull/3313)]
|
||||
- enhance: send events for adding/removing favourite items [[#3229](https://github.com/opencloud-eu/opencloud/pull/3229)]
|
||||
- allow tuning the proxies http client [[#3278](https://github.com/opencloud-eu/opencloud/pull/3278)]
|
||||
- feat(web): add yjsServerUrl config [[#3259](https://github.com/opencloud-eu/opencloud/pull/3259)]
|
||||
- feat(posixfs): #3182 add basepath option in the "posixfs scan" command [[#3235](https://github.com/opencloud-eu/opencloud/pull/3235)]
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- fix(search): refresh the opensearch index after a write [[#3388](https://github.com/opencloud-eu/opencloud/pull/3388)]
|
||||
- fix(thumbnails): respect the requested height in libvips builds [[#3377](https://github.com/opencloud-eu/opencloud/pull/3377)]
|
||||
- refactor datagateway into proxy middleware [[#3289](https://github.com/opencloud-eu/opencloud/pull/3289)]
|
||||
- Only log a debug message when an item is still in processing state [[#3158](https://github.com/opencloud-eu/opencloud/pull/3158)]
|
||||
- fix(postprocessing): retry publishing events instead of killing the server [[#3347](https://github.com/opencloud-eu/opencloud/pull/3347)]
|
||||
- actually log error on exit [[#3344](https://github.com/opencloud-eu/opencloud/pull/3344)]
|
||||
- fix(activitylog): log missing parent id cache entry at debug level [[#3325](https://github.com/opencloud-eu/opencloud/pull/3325)]
|
||||
- fix restore file version for shared resource [[#3268](https://github.com/opencloud-eu/opencloud/pull/3268)]
|
||||
- Fix missing favorite flag on opensearch hits [[#3252](https://github.com/opencloud-eu/opencloud/pull/3252)]
|
||||
|
||||
### 📚 Documentation
|
||||
|
||||
- docs: clarify custom role bootstrap behavior [[#3366](https://github.com/opencloud-eu/opencloud/pull/3366)]
|
||||
|
||||
### 📦️ Dependencies
|
||||
|
||||
- [full-ci] chore: bump web to v7.4.0 [[#3399](https://github.com/opencloud-eu/opencloud/pull/3399)]
|
||||
- build(deps): bump google.golang.org/grpc from 1.83.0 to 1.83.1 [[#3396](https://github.com/opencloud-eu/opencloud/pull/3396)]
|
||||
- build(deps): bump github.com/stretchr/testify from 1.12.0 to 1.12.1 [[#3395](https://github.com/opencloud-eu/opencloud/pull/3395)]
|
||||
- build(deps): bump github.com/go-chi/chi/v5 from 5.3.1 to 5.3.2 [[#3394](https://github.com/opencloud-eu/opencloud/pull/3394)]
|
||||
- build(deps): bump github.com/grpc-ecosystem/grpc-gateway/v2 from 2.29.0 to 2.30.0 [[#3380](https://github.com/opencloud-eu/opencloud/pull/3380)]
|
||||
- build(deps): bump golang.org/x/image from 0.44.0 to 0.45.0 [[#3381](https://github.com/opencloud-eu/opencloud/pull/3381)]
|
||||
- build(deps): bump github.com/beevik/etree from 1.7.0 to 1.7.1 [[#3382](https://github.com/opencloud-eu/opencloud/pull/3382)]
|
||||
- build(deps): bump github.com/nats-io/nats-server/v2 from 2.14.4 to 2.14.5 [[#3357](https://github.com/opencloud-eu/opencloud/pull/3357)]
|
||||
- build(deps): bump go.opentelemetry.io/contrib/zpages from 0.69.0 to 0.70.0 [[#3360](https://github.com/opencloud-eu/opencloud/pull/3360)]
|
||||
- build(deps): bump github.com/sirupsen/logrus from 1.9.4 to 1.10.0 [[#3359](https://github.com/opencloud-eu/opencloud/pull/3359)]
|
||||
- chore: bump reva to latest main [[#3329](https://github.com/opencloud-eu/opencloud/pull/3329)]
|
||||
- build(deps): bump github.com/stretchr/testify from 1.11.1 to 1.12.0 [[#3341](https://github.com/opencloud-eu/opencloud/pull/3341)]
|
||||
- build(deps): bump golang.org/x/net from 0.57.0 to 0.58.0 [[#3342](https://github.com/opencloud-eu/opencloud/pull/3342)]
|
||||
- build(deps): bump github.com/onsi/ginkgo/v2 from 2.32.0 to 2.32.1 [[#3340](https://github.com/opencloud-eu/opencloud/pull/3340)]
|
||||
- build(deps): bump github.com/testcontainers/testcontainers-go/modules/opensearch from 0.43.0 to 0.44.0 [[#3303](https://github.com/opencloud-eu/opencloud/pull/3303)]
|
||||
- build(deps): bump github.com/opencloud-eu/libre-graph-api-go [[#3326](https://github.com/opencloud-eu/opencloud/pull/3326)]
|
||||
- build(deps): bump go.opentelemetry.io/otel/exporters/stdout/stdouttrace from 1.44.0 to 1.45.0 [[#3306](https://github.com/opencloud-eu/opencloud/pull/3306)]
|
||||
- build(deps): bump go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp from 0.69.0 to 0.70.0 [[#3305](https://github.com/opencloud-eu/opencloud/pull/3305)]
|
||||
- build(deps): bump go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc from 1.44.0 to 1.45.0 [[#3280](https://github.com/opencloud-eu/opencloud/pull/3280)]
|
||||
- build(deps): bump github.com/rogpeppe/go-internal from 1.15.0 to 1.16.0 [[#3250](https://github.com/opencloud-eu/opencloud/pull/3250)]
|
||||
- build(deps): bump github.com/kovidgoyal/imaging from 1.8.22 to 1.8.23 [[#3135](https://github.com/opencloud-eu/opencloud/pull/3135)]
|
||||
- build(deps): bump go.opentelemetry.io/otel/trace from 1.44.0 to 1.45.0 [[#3266](https://github.com/opencloud-eu/opencloud/pull/3266)]
|
||||
|
||||
## [7.4.0](https://github.com/opencloud-eu/opencloud/releases/tag/v7.4.0) - 2026-08-03
|
||||
|
||||
### ❤️ Thanks to all contributors! ❤️
|
||||
|
||||
@AlexAndBear, @JammingBen, @aduffeck, @dschmidt, @fschade, @michaelstingl, @pbleser-oc, @rhafer, @schweigisito, @v-scharf
|
||||
|
||||
### 📈 Enhancement
|
||||
|
||||
- Do not check ignored paths [[#3233](https://github.com/opencloud-eu/opencloud/pull/3233)]
|
||||
- Extend posixfs consistency check [[#3220](https://github.com/opencloud-eu/opencloud/pull/3220)]
|
||||
- Improve reindex command [[#3213](https://github.com/opencloud-eu/opencloud/pull/3213)]
|
||||
- Reindex spaces concurrently [[#3207](https://github.com/opencloud-eu/opencloud/pull/3207)]
|
||||
- feat: add announcement banner [[#3189](https://github.com/opencloud-eu/opencloud/pull/3189)]
|
||||
- feat: add space viewer with versions role [[#2961](https://github.com/opencloud-eu/opencloud/pull/2961)]
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- fix(runtime): log service startup errors instead of printing them beside the log [[#3140](https://github.com/opencloud-eu/opencloud/pull/3140)]
|
||||
- fix(posixfs scan): Setup logger for scan command [[#3185](https://github.com/opencloud-eu/opencloud/pull/3185)]
|
||||
|
||||
### ✅ Tests
|
||||
|
||||
- api-test: mark group last-manager removal scenario as flaky [[#3194](https://github.com/opencloud-eu/opencloud/pull/3194)]
|
||||
- rerun flaky tests [[#3183](https://github.com/opencloud-eu/opencloud/pull/3183)]
|
||||
- api-test: fix removeAccessToDrive.feature:145 [[#3179](https://github.com/opencloud-eu/opencloud/pull/3179)]
|
||||
- api-test: cover additional unified roles in acceptance tests [[#3169](https://github.com/opencloud-eu/opencloud/pull/3169)]
|
||||
- test(apiAuthApp): fix flaky token pattern [[#3163](https://github.com/opencloud-eu/opencloud/pull/3163)]
|
||||
- test(apiArchiver): the single-resource archive is named after the resource [[#3080](https://github.com/opencloud-eu/opencloud/pull/3080)]
|
||||
- test(coreApiWebdavUploadTUS): assert etag and permissions on the finalizing TUS chunk [[#3078](https://github.com/opencloud-eu/opencloud/pull/3078)]
|
||||
- test(coreApiWebdavOperations): download a file with a literal "%" via its oc:downloadURL [[#3079](https://github.com/opencloud-eu/opencloud/pull/3079)]
|
||||
|
||||
### 📚 Documentation
|
||||
|
||||
- maint: clean-up auth-app documentation [[#3155](https://github.com/opencloud-eu/opencloud/pull/3155)]
|
||||
- ci: sync tests/README.md to docs [[#3164](https://github.com/opencloud-eu/opencloud/pull/3164)]
|
||||
|
||||
### 📦️ Dependencies
|
||||
|
||||
- [full-ci] chore: bump web to v7.3.0 [[#3223](https://github.com/opencloud-eu/opencloud/pull/3223)]
|
||||
- build(deps): bump github.com/open-policy-agent/opa from 1.18.2 to 1.19.0 [[#3231](https://github.com/opencloud-eu/opencloud/pull/3231)]
|
||||
- build(deps): bump google.golang.org/grpc from 1.82.0 to 1.83.0 [[#3232](https://github.com/opencloud-eu/opencloud/pull/3232)]
|
||||
- chore(idp): bump dependencies [[#3226](https://github.com/opencloud-eu/opencloud/pull/3226)]
|
||||
- build(deps): bump github.com/nats-io/nats-server/v2 from 2.14.3 to 2.14.4 [[#3221](https://github.com/opencloud-eu/opencloud/pull/3221)]
|
||||
- build(deps): bump github.com/go-ldap/ldap/v3 from 3.4.13 to 3.4.14 [[#3222](https://github.com/opencloud-eu/opencloud/pull/3222)]
|
||||
- build(deps): bump github.com/prometheus/client_golang from 1.23.2 to 1.24.1 [[#3218](https://github.com/opencloud-eu/opencloud/pull/3218)]
|
||||
- build(deps): bump github.com/gabriel-vasile/mimetype from 1.4.13 to 1.4.15 [[#3217](https://github.com/opencloud-eu/opencloud/pull/3217)]
|
||||
- build(deps): bump golang.org/x/net from 0.56.0 to 0.57.0 [[#3136](https://github.com/opencloud-eu/opencloud/pull/3136)]
|
||||
- build(deps): bump github.com/beevik/etree from 1.6.0 to 1.7.0 [[#3134](https://github.com/opencloud-eu/opencloud/pull/3134)]
|
||||
|
||||
## [7.3.0](https://github.com/opencloud-eu/opencloud/releases/tag/v7.3.0) - 2026-07-14
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- fix(proxy): honor access token cache ttl [[#3056](https://github.com/opencloud-eu/opencloud/pull/3056)]
|
||||
- chore(idp): update axios [[#3094](https://github.com/opencloud-eu/opencloud/pull/3094)]
|
||||
- fix: make the collaboration service events optional [[#3001](https://github.com/opencloud-eu/opencloud/pull/3001)]
|
||||
- Revert "fix: disallow thumbnails for tiff and jpeg2000 images" [[#2973](https://github.com/opencloud-eu/opencloud/pull/2973)]
|
||||
- bump reva [[#2950](https://github.com/opencloud-eu/opencloud/pull/2950)]
|
||||
- change error level for trashing items interaction with search [[#2951](https://github.com/opencloud-eu/opencloud/pull/2951)]
|
||||
- fix: Send SSE events for SpaceEnabled/Disabled to affected users [[#2871](https://github.com/opencloud-eu/opencloud/pull/2871)]
|
||||
|
||||
### 📚 Documentation
|
||||
|
||||
- update collaboration readme [[#3076](https://github.com/opencloud-eu/opencloud/pull/3076)]
|
||||
- fix: fix typo in proxy service documentation [[#3089](https://github.com/opencloud-eu/opencloud/pull/3089)]
|
||||
- roling release template [[#2972](https://github.com/opencloud-eu/opencloud/pull/2972)]
|
||||
- enhance: fix typos in webfinger service description [[#2958](https://github.com/opencloud-eu/opencloud/pull/2958)]
|
||||
|
||||
### ✅ Tests
|
||||
|
||||
- [full-ci] gherkin steps refactoring. cleaning code [[#3100](https://github.com/opencloud-eu/opencloud/pull/3100)]
|
||||
- [decomposed] more cli command tests [[#3087](https://github.com/opencloud-eu/opencloud/pull/3087)]
|
||||
- test(apiSpaces): a space admin can delete a space with no manager [[#3040](https://github.com/opencloud-eu/opencloud/pull/3040)]
|
||||
- Update tests for opencloud-eu/reva#655 [[#2889](https://github.com/opencloud-eu/opencloud/pull/2889)]
|
||||
- api-test: deleting space [[#2970](https://github.com/opencloud-eu/opencloud/pull/2970)]
|
||||
|
||||
### 📈 Enhancement
|
||||
|
||||
- feat: add disableSponsorLink web config option [[#3093](https://github.com/opencloud-eu/opencloud/pull/3093)]
|
||||
- feat(graph): add MS Graph colon-syntax path lookup middleware [[#2688](https://github.com/opencloud-eu/opencloud/pull/2688)]
|
||||
- feat: adjust theme chrome colors and logos [[#2599](https://github.com/opencloud-eu/opencloud/pull/2599)]
|
||||
- add tls support for all nats connections [[#2063](https://github.com/opencloud-eu/opencloud/pull/2063)]
|
||||
- feat: add more roles [[#2928](https://github.com/opencloud-eu/opencloud/pull/2928)]
|
||||
- next to main [[#2924](https://github.com/opencloud-eu/opencloud/pull/2924)]
|
||||
- feat: add core apps env variable to override the default core apps [[#2930](https://github.com/opencloud-eu/opencloud/pull/2930)]
|
||||
|
||||
### 📦️ Dependencies
|
||||
|
||||
- build(deps): bump golang.org/x/image from 0.43.0 to 0.44.0 [[#3112](https://github.com/opencloud-eu/opencloud/pull/3112)]
|
||||
- build(deps): bump golang.org/x/text from 0.39.0 to 0.40.0 [[#3101](https://github.com/opencloud-eu/opencloud/pull/3101)]
|
||||
- [full-ci] chore: bump web to v7.2.0 [[#3121](https://github.com/opencloud-eu/opencloud/pull/3121)]
|
||||
- build(deps): bump golang.org/x/term from 0.44.0 to 0.45.0 [[#3103](https://github.com/opencloud-eu/opencloud/pull/3103)]
|
||||
- build(deps): bump github.com/coreos/go-oidc/v3 from 3.19.0 to 3.20.0 [[#3102](https://github.com/opencloud-eu/opencloud/pull/3102)]
|
||||
- build(deps): bump golang.org/x/text from 0.38.0 to 0.39.0 [[#3085](https://github.com/opencloud-eu/opencloud/pull/3085)]
|
||||
- build(deps): bump github.com/go-chi/chi/v5 from 5.3.0 to 5.3.1 [[#3073](https://github.com/opencloud-eu/opencloud/pull/3073)]
|
||||
- build(deps): bump github.com/nats-io/nats-server/v2 from 2.14.2 to 2.14.3 [[#3063](https://github.com/opencloud-eu/opencloud/pull/3063)]
|
||||
- build(deps): bump github.com/gookit/config/v2 from 2.2.8 to 2.2.9 [[#3075](https://github.com/opencloud-eu/opencloud/pull/3075)]
|
||||
- build(deps): bump github.com/open-policy-agent/opa from 1.18.1 to 1.18.2 [[#3061](https://github.com/opencloud-eu/opencloud/pull/3061)]
|
||||
- build(deps): bump github.com/kovidgoyal/imaging from 1.8.21 to 1.8.22 [[#3060](https://github.com/opencloud-eu/opencloud/pull/3060)]
|
||||
- build(deps): bump github.com/libregraph/lico from 0.66.0 to 0.67.0 [[#3028](https://github.com/opencloud-eu/opencloud/pull/3028)]
|
||||
- chore: bump web to v7.2.0-beta.3 [[#2953](https://github.com/opencloud-eu/opencloud/pull/2953)]
|
||||
- chore: bump reva to latest main [[#2943](https://github.com/opencloud-eu/opencloud/pull/2943)]
|
||||
|
||||
## [7.2.0](https://github.com/opencloud-eu/opencloud/releases/tag/v7.2.0) - 2026-06-24
|
||||
|
||||
### ❤️ Thanks to all contributors! ❤️
|
||||
|
||||
@Heiko-Pohl, @JammingBen, @ScharfViktor, @aduffeck, @butonic, @dragonchaser, @kulmann, @rhafer
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- [stable-7.2] Backport fixes from main [[#2999](https://github.com/opencloud-eu/opencloud/pull/2999)]
|
||||
- fix(idp): aarch64 build [[#2906](https://github.com/opencloud-eu/opencloud/pull/2906)]
|
||||
- use ldap instead of ldaps internally [[#2880](https://github.com/opencloud-eu/opencloud/pull/2880)]
|
||||
|
||||
### 📚 Documentation
|
||||
|
||||
- Rename role_name from "guest" to "user-light" [[#2912](https://github.com/opencloud-eu/opencloud/pull/2912)]
|
||||
|
||||
### 📦️ Dependencies
|
||||
|
||||
- [full-ci] chore: bump web to v7.1.2 [[#3012](https://github.com/opencloud-eu/opencloud/pull/3012)]
|
||||
- [full-ci] chore: bump web to v7.1.1 [[#2998](https://github.com/opencloud-eu/opencloud/pull/2998)]
|
||||
- bump reva to latest main [[#2922](https://github.com/opencloud-eu/opencloud/pull/2922)]
|
||||
- build(deps-dev): bump webpack-manifest-plugin from 5.0.0 to 6.0.1 in /services/idp [[#2884](https://github.com/opencloud-eu/opencloud/pull/2884)]
|
||||
- build(deps): bump axios from 1.16.0 to 1.16.1 in /services/idp [[#2883](https://github.com/opencloud-eu/opencloud/pull/2883)]
|
||||
|
||||
## [7.1.0](https://github.com/opencloud-eu/opencloud/releases/tag/v7.1.0) - 2026-06-02
|
||||
|
||||
### ❤️ Thanks to all contributors! ❤️
|
||||
|
||||
+2
-3
@@ -21,15 +21,14 @@ COPY ./ /opencloud/
|
||||
WORKDIR /opencloud/opencloud
|
||||
RUN make node-generate-prod
|
||||
|
||||
FROM golang:1.24-alpine AS build
|
||||
RUN apk add bash make git curl gcc musl-dev libc-dev binutils-gold inotify-tools vips-dev
|
||||
FROM quay.io/opencloudeu/golang-ci:1.25 AS build
|
||||
|
||||
COPY --from=generate /opencloud /opencloud
|
||||
|
||||
WORKDIR /opencloud/opencloud
|
||||
RUN make go-generate build ENABLE_VIPS=true
|
||||
|
||||
FROM alpine:3.23
|
||||
FROM alpine:3.24
|
||||
|
||||
RUN apk add --no-cache attr ca-certificates curl mailcap tree vips && \
|
||||
echo 'hosts: files dns' >| /etc/nsswitch.conf
|
||||
|
||||
@@ -68,11 +68,8 @@ OC_MODULES = \
|
||||
protogen
|
||||
|
||||
# bin file definitions
|
||||
PHP_CS_FIXER=php -d zend.enable_gc=0 vendor-bin/opencloud-codestyle/vendor/bin/php-cs-fixer
|
||||
PHP_CODESNIFFER=vendor-bin/php_codesniffer/vendor/bin/phpcs
|
||||
PHP_CODEBEAUTIFIER=vendor-bin/php_codesniffer/vendor/bin/phpcbf
|
||||
PHAN=php -d zend.enable_gc=0 vendor-bin/phan/vendor/bin/phan
|
||||
PHPSTAN=php -d zend.enable_gc=0 vendor-bin/phpstan/vendor/bin/phpstan
|
||||
PHP_CODESNIFFER=vendor-bin/opencloud-codestyle/vendor/bin/phpcs
|
||||
PHP_CODEBEAUTIFIER=vendor-bin/opencloud-codestyle/vendor/bin/phpcbf
|
||||
|
||||
ifneq (, $(shell command -v go 2> /dev/null)) # suppress `command not found warnings` for non go targets in CI
|
||||
include .bingo/Variables.mk
|
||||
@@ -107,6 +104,7 @@ help:
|
||||
@echo -e "${GREEN}Tools for linting gherkin feature files:\n${RESET}"
|
||||
@echo -e "\tmake test-gherkin-lint\t\t${BLUE}run lint checks on Gherkin feature files${RESET}"
|
||||
@echo -e "\tmake test-gherkin-lint-fix\t${BLUE}apply lint fixes to gherkin feature files${RESET}"
|
||||
@echo -e "\tmake find-unused-steps\t\t${BLUE}list Behat step definitions unused by any .feature file${RESET}"
|
||||
@echo
|
||||
|
||||
.PHONY: clean-tests
|
||||
@@ -228,6 +226,10 @@ test-gherkin-lint:
|
||||
test-gherkin-lint-fix:
|
||||
gherlint --fix tests/acceptance/features -c tests/acceptance/config/.gherlintrc.json
|
||||
|
||||
.PHONY: find-unused-steps
|
||||
find-unused-steps: vendor-bin/behat/vendor
|
||||
tests/acceptance/scripts/find-unused-steps.sh
|
||||
|
||||
.PHONY: bingo-update
|
||||
bingo-update: $(BINGO)
|
||||
$(BINGO) get -l -v -t 20
|
||||
@@ -314,37 +316,15 @@ ci-format: $(BUILDIFIER)
|
||||
$(BUILDIFIER) --mode=fix .woodpecker.star
|
||||
|
||||
.PHONY: test-php-style
|
||||
test-php-style: vendor-bin/opencloud-codestyle/vendor vendor-bin/php_codesniffer/vendor
|
||||
$(PHP_CS_FIXER) fix -v --diff --allow-risky yes --dry-run
|
||||
test-php-style: vendor-bin/opencloud-codestyle/vendor
|
||||
$(PHP_CODESNIFFER) --cache --runtime-set ignore_warnings_on_exit --standard=phpcs.xml tests/acceptance tests/acceptance/TestHelpers
|
||||
|
||||
.PHONY: test-php-style-fix
|
||||
test-php-style-fix: vendor-bin/opencloud-codestyle/vendor
|
||||
$(PHP_CS_FIXER) fix -v --diff --allow-risky yes
|
||||
$(PHP_CODEBEAUTIFIER) --cache --runtime-set ignore_warnings_on_exit --standard=phpcs.xml tests/acceptance
|
||||
|
||||
.PHONY: vendor-bin-codestyle
|
||||
vendor-bin-codestyle: vendor-bin/opencloud-codestyle/vendor
|
||||
|
||||
.PHONY: vendor-bin-codesniffer
|
||||
vendor-bin-codesniffer: vendor-bin/php_codesniffer/vendor
|
||||
|
||||
vendor-bin/opencloud-codestyle/vendor: vendor/bamarni/composer-bin-plugin vendor-bin/opencloud-codestyle/composer.lock
|
||||
composer bin opencloud-codestyle install --no-progress
|
||||
|
||||
vendor-bin/opencloud-codestyle/composer.lock: vendor-bin/opencloud-codestyle/composer.json
|
||||
@echo opencloud-codestyle composer.lock is not up to date.
|
||||
|
||||
vendor-bin/php_codesniffer/vendor: vendor/bamarni/composer-bin-plugin vendor-bin/php_codesniffer/composer.lock
|
||||
composer bin php_codesniffer install --no-progress
|
||||
|
||||
vendor-bin/php_codesniffer/composer.lock: vendor-bin/php_codesniffer/composer.json
|
||||
@echo php_codesniffer composer.lock is not up to date.
|
||||
|
||||
.PHONY: generate-qa-activity-report
|
||||
generate-qa-activity-report: node_modules
|
||||
@if [ -z "${MONTH}" ] || [ -z "${YEAR}" ]; then \
|
||||
echo "Please set the MONTH and YEAR environment variables. Usage: make generate-qa-activity-report MONTH=<month> YEAR=<year>"; \
|
||||
exit 1; \
|
||||
fi
|
||||
go run tests/qa-activity-report/generate-qa-activity-report.go --month ${MONTH} --year ${YEAR}
|
||||
@@ -1,62 +0,0 @@
|
||||
# Table of Contents
|
||||
|
||||
{{ range . -}}
|
||||
* [Changelog for {{ .Version }}](#changelog-for-{{ .Version | replace "." ""}}-{{ .Date | lower -}})
|
||||
{{ end -}}
|
||||
{{ $allVersions := . }}
|
||||
{{- range $index, $changes := . }}{{ with $changes -}}
|
||||
{{ if gt (len $allVersions) 1 }}
|
||||
# Changelog for [{{ .Version }}] ({{ .Date }})
|
||||
|
||||
The following sections list the changes for {{ .Version}}.
|
||||
|
||||
{{/* creating version compare links */ -}}
|
||||
{{ $next := add1 $index -}}
|
||||
{{ if ne (len $allVersions) $next -}}
|
||||
{{ $previousVersion := (index $allVersions $next).Version -}}
|
||||
{{ if eq .Version "unreleased" -}}
|
||||
[{{ .Version}}]: https://github.com/opencloud-eu/opencloud/compare/v{{ $previousVersion }}...master
|
||||
|
||||
{{ else -}}
|
||||
[{{ .Version}}]: https://github.com/opencloud-eu/opencloud/compare/v{{ $previousVersion }}...v{{ .Version}}
|
||||
|
||||
{{ end -}}
|
||||
{{ end -}}
|
||||
|
||||
{{- /* last version managed by calens, end of the loop */ -}}
|
||||
{{ if eq .Version "0.1.0" -}}
|
||||
[{{ .Version }}]: https://github.com/opencloud-eu/opencloud/compare/94f19e653e30cdf16dcf23dbaf36c6d753d37ae9...v{{ .Version }}
|
||||
|
||||
{{ end -}}
|
||||
{{ else -}}
|
||||
# Changes in {{ .Version}}
|
||||
|
||||
{{ end -}}
|
||||
|
||||
## Summary
|
||||
{{ range $entry := .Entries }}{{ with $entry }}
|
||||
* {{ .Type }} - {{ .Title }}: [#{{ .PrimaryID }}]({{ .PrimaryURL }})
|
||||
{{- end }}{{ end }}
|
||||
|
||||
## Details
|
||||
{{ range $entry := .Entries }}{{ with $entry }}
|
||||
* {{ .Type }} - {{ .Title }}: [#{{ .PrimaryID }}]({{ .PrimaryURL }})
|
||||
{{ range $par := .Paragraphs -}}
|
||||
{{/* Workaround for keeping lists inside of changelog items well formatted */ -}}
|
||||
{{ if hasPrefix "*" $par }}
|
||||
{{ $par | replace " *" "\n *" }}
|
||||
{{- else }}
|
||||
{{ wrapIndent $par 80 3 -}}
|
||||
{{ end }}
|
||||
{{ end -}}
|
||||
{{ range $url := .IssueURLs }}
|
||||
{{ $url -}}
|
||||
{{ end -}}
|
||||
{{ range $url := .PRURLs }}
|
||||
{{ $url -}}
|
||||
{{ end -}}
|
||||
{{ range $url := .OtherURLs }}
|
||||
{{ $url -}}
|
||||
{{ end }}
|
||||
{{ end }}{{ end -}}
|
||||
{{ end }}{{ end -}}
|
||||
@@ -1,16 +0,0 @@
|
||||
# Changelog
|
||||
|
||||
We are using [calens](https://github.com/restic/calens) to properly generate a
|
||||
changelog before we are tagging a new release. To get an idea how this could
|
||||
look like <https://github.com/restic/restic/tree/master/changelog> would be the
|
||||
best reference.
|
||||
|
||||
## Create changelog items
|
||||
|
||||
Create a file according to the template for each changelog in the unreleased folder.
|
||||
The following change types are possible:
|
||||
- Bugfix (general Bugfix)
|
||||
- Enhancement (new feature)
|
||||
- Change (breaking change)
|
||||
- Security (security related issues)
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
Bugfix: Fix behavior for foobar (in present tense)
|
||||
|
||||
We've fixed the behavior for foobar, a long-standing annoyance for users. The
|
||||
text should be wrapped at 80 characters length.
|
||||
|
||||
The text in the paragraphs is written in past tense. The last section is a list
|
||||
of issue URLs, PR URLs and other URLs. The first issue ID (or the first PR ID,
|
||||
in case there aren't any issue links) is used as the primary ID.
|
||||
|
||||
https://github.com/opencloud-eu/opencloud/pull/55555
|
||||
https://github.com/opencloud-eu/opencloud/issues/1234
|
||||
|
||||
Note: Possible keywords are Bugfixes (for bug fixes), Enhancement (for new features),
|
||||
Change (for breaking changes), Security (for security related topics)
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
## Release, Date, Type, Title, Primary ID, Primary URL
|
||||
{{ range . -}}
|
||||
{{ $v := .Version -}}
|
||||
{{ $d := .Date -}}
|
||||
{{ range $entry := .Entries -}}
|
||||
{{ $v }},{{ $d }},{{ .Type }},'{{ .Title }}',{{ .PrimaryID }},{{ .PrimaryURL }}
|
||||
{{ end -}}
|
||||
{{ end -}}
|
||||
Whitespace-only changes.
@@ -1,7 +0,0 @@
|
||||
Enhancement: Add WAYF configuration for reva OCM service
|
||||
|
||||
Add WAYF configuration support for the Reva OCM service,
|
||||
enabling federation discovery functionality for Open Cloud Mesh.
|
||||
This includes configuration for federations file storage and invite accept dialog URL.
|
||||
|
||||
https://github.com/opencloud-eu/opencloud/pull/1714
|
||||
@@ -1,9 +0,0 @@
|
||||
Bugfix: Don't re-escape notification email vars for each recipient
|
||||
|
||||
When a notification went to several recipients in one call (e.g. a group
|
||||
invite to a space), each recipient past the first got subjects and bodies
|
||||
with one extra layer of HTML escaping. escapeStringMap mutated its input
|
||||
map, and the recipient loop reused the same map across iterations. It now
|
||||
returns a new map.
|
||||
|
||||
https://github.com/opencloud-eu/opencloud/issues/2804
|
||||
@@ -0,0 +1,21 @@
|
||||
Bugfix: Retry publishing postprocessing events before giving up
|
||||
|
||||
A single transient failure while publishing an event to the event system took
|
||||
the whole server down. The postprocessing service treated every publish error
|
||||
as fatal and called log.Fatal, which exits the process and so also stopped all
|
||||
the other services running in the same binary. A burst of uploads was enough to
|
||||
run into one nats publish timeout and lose the server with it.
|
||||
|
||||
Publishing is now retried using the same exponential backoff that is already
|
||||
used for failed postprocessing steps. Between the attempts the source event is
|
||||
marked as in progress and the backoff is capped at half the ack wait, so the
|
||||
event should not be redelivered to another worker while we are still retrying.
|
||||
The number of retries is configurable via POSTPROCESSING_PUBLISH_MAX_RETRIES.
|
||||
|
||||
Should all attempts fail, the source event is no longer acknowledged. Before,
|
||||
the event was acknowledged even though its successor was never published, so
|
||||
the upload was left half processed in the store and did not recover on restart.
|
||||
|
||||
https://github.com/opencloud-eu/opencloud/issues/3271
|
||||
https://github.com/opencloud-eu/opencloud/issues/2232
|
||||
https://github.com/opencloud-eu/opencloud/issues/2422
|
||||
+4
-3
@@ -2,7 +2,7 @@
|
||||
"name": "opencloud-eu/opencloud",
|
||||
"config": {
|
||||
"platform": {
|
||||
"php": "8.3"
|
||||
"php": "8.4"
|
||||
},
|
||||
"vendor-dir": "./vendor-php",
|
||||
"allow-plugins": {
|
||||
@@ -11,11 +11,12 @@
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-simplexml": "*",
|
||||
"bamarni/composer-bin-plugin": "^1.8"
|
||||
"bamarni/composer-bin-plugin": "^1.9"
|
||||
},
|
||||
"extra": {
|
||||
"bamarni-bin": {
|
||||
"bin-links": false
|
||||
"bin-links": false,
|
||||
"forward-command": false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,3 +45,4 @@ directives:
|
||||
style-src:
|
||||
- '''self'''
|
||||
- '''unsafe-inline'''
|
||||
- 'blob:'
|
||||
@@ -42,3 +42,4 @@ directives:
|
||||
style-src:
|
||||
- '''self'''
|
||||
- '''unsafe-inline'''
|
||||
- 'blob:'
|
||||
@@ -0,0 +1,226 @@
|
||||
---
|
||||
title: "5. Unified Search Index Mapping"
|
||||
---
|
||||
|
||||
* Status: accepted
|
||||
* Deciders: @aduffeck, @butonic, @dschmidt, @fschade
|
||||
* Date: 2026-04-23, accepted and updated to the implemented state 2026-08-31
|
||||
|
||||
Reference: implemented by https://github.com/opencloud-eu/opencloud/pull/3345 (reflection-based mapping, search siblings, shared query lowering) and https://github.com/opencloud-eu/opencloud/pull/3197 (schema versioning and startup checks). https://github.com/opencloud-eu/opencloud/pull/2659 was the original proof-of-concept.
|
||||
|
||||
## Context and Problem Statement
|
||||
|
||||
This section describes the state at decision time (April 2026); the implementation has since resolved the problems listed here.
|
||||
|
||||
The search service supports two backends, bleve (embedded) and
|
||||
OpenSearch (external). Each backend currently carries its own,
|
||||
independently maintained description of the index layout:
|
||||
|
||||
- The bleve backend hand-builds a document mapping that explicitly
|
||||
declares only Name, Tags, Favorites and Content. Everything else,
|
||||
including the entire facet block (audio, image, photo, location),
|
||||
is left to bleve's dynamic mapping.
|
||||
- The OpenSearch backend ships a static JSON template that covers a
|
||||
similar but not identical subset, plus a few OpenSearch-specific
|
||||
primitives (path_hierarchy analyzer, wildcard MimeType). It does
|
||||
not list the facet sub-fields either; they are produced by
|
||||
OpenSearch's dynamic templating at first write.
|
||||
- The graph DriveItem assembly path keeps its own private copy of a
|
||||
reflection-based walker to turn CS3 ArbitraryMetadata back into
|
||||
typed libregraph facets, parallel to the search service's
|
||||
reflection helpers but maintained separately.
|
||||
- The bleve KQL compiler keeps a hand-maintained set of field names
|
||||
whose query values need to be pre-lowercased, with a comment that
|
||||
literally says "Keep in sync with index.go".
|
||||
|
||||
The current implementation has three concrete problems:
|
||||
|
||||
1. **The two backends do not behave the same.** Both rely on their
|
||||
own implicit defaults for fields that are not explicitly
|
||||
declared. The inferred shapes differ: bleve produces keyword-
|
||||
analyzed text, OpenSearch produces a `text + keyword` multi-field
|
||||
with auto-detected dates. Nobody has written down which behavior
|
||||
is the intended one. Two concrete instances surfaced while building
|
||||
#2659:
|
||||
- **mtime** is stored as an RFC3339 string. OpenSearch's dynamic
|
||||
mapping auto-detects it as `date`; bleve leaves it `keyword`. So
|
||||
`mtime:>...` is a chronological range on OpenSearch but a
|
||||
lexicographic string compare on bleve.
|
||||
- **name/tags**: bleve indexes a single lowercase token (exact or
|
||||
wildcard match only); OpenSearch word-tokenizes, so a bare
|
||||
`name:report` matches "My Report.txt" on OpenSearch but not on
|
||||
bleve.
|
||||
2. **Drift risk.** The OpenSearch JSON template is a subset of what
|
||||
actually gets indexed. Even where it overlaps with the bleve
|
||||
mapping it diverges on analyzer choices. Because the facet
|
||||
fields were not reachable from user queries at the time (no dot
|
||||
syntax in the KQL compilers, no facet exposure on the hit and
|
||||
REPORT paths), the divergence has been invisible, but it would
|
||||
surface the moment the first working cross-backend facet query
|
||||
landed.
|
||||
3. **Per-facet cost.** Adding a new facet (motionPhoto, etc.)
|
||||
requires coordinated edits across the proto message, both backend
|
||||
mappings, the bleve hit converters, the OpenSearch convert
|
||||
closures, the search service's metadata persistence, the graph
|
||||
DriveItem assembly, and the KQL compiler's lowercasing set. Most
|
||||
of those edits are boilerplate following a copy-paste pattern.
|
||||
Adding a genuinely new index capability (geopoint, wildcard,
|
||||
...) means wiring it in at every one of those sites, and there
|
||||
is no single place to hook a type-specific adapter.
|
||||
|
||||
### A note on backwards compatibility
|
||||
|
||||
That the facet fields were unreachable at decision time has a
|
||||
useful corollary for this ADR: **changing the indexed shape of the
|
||||
facet fields cannot break any existing client of the search
|
||||
service**, because no client could successfully read them. The behavior changes
|
||||
discussed below are therefore additive in a literal sense; nothing
|
||||
that works today stops working as a result.
|
||||
|
||||
## Decision Drivers
|
||||
|
||||
* **Predictable OpenCloud API behavior independent of backend.**
|
||||
Consumers of the search service should be able to rely on the
|
||||
documented behavior of the API, not on which backend happens to
|
||||
be configured. Today the same query can give different results
|
||||
depending on whether bleve or OpenSearch is wired in (bleve's
|
||||
dynamic default is `keyword`, exact match; OpenSearch's dynamic
|
||||
default is `text + keyword`, also matches sub-tokens of a
|
||||
string). That is backend-implementation leakage, and trying to
|
||||
keep the two implicit defaults synchronized has not worked.
|
||||
* Single source of truth for the indexed schema, so the two backends
|
||||
cannot drift silently again.
|
||||
* Reduce the per-facet cost so future facets (motionPhoto and
|
||||
whatever comes next) can be added with minimal boilerplate.
|
||||
* Establish a single place to hook index-type-specific behavior, so
|
||||
a new capability needs to be implemented at most once per backend
|
||||
and then becomes available for any field uniformly.
|
||||
* A one-time reindex is an acceptable upgrade path. Both bleve and
|
||||
OpenSearch store their mapping alongside the data; existing
|
||||
indexes keep serving queries against their stored shape without
|
||||
any automatic reshaping. Benefiting from the new behavior is done
|
||||
by creating a fresh index and re-ingesting, which is the normal
|
||||
reindex flow, rather than by inventing migration tooling.
|
||||
|
||||
## Considered Options
|
||||
|
||||
### Option 1: Do nothing, keep relying on implicit backend defaults
|
||||
|
||||
Accept that bleve and OpenSearch each fall back to their own
|
||||
dynamic-mapping defaults for whatever is not explicitly declared,
|
||||
and treat the observable search behavior of OpenCloud as "whatever
|
||||
the configured backend happens to do". Adding a facet stays a
|
||||
copy-paste coordination across half a dozen sites; the existing
|
||||
divergence between bleve (keyword) and OpenSearch (`text + keyword`
|
||||
multi-field plus auto-date detection) stays silently in place
|
||||
until a working query actually reaches the diverging field and
|
||||
returns different answers on the two backends.
|
||||
|
||||
Low upfront work, but it makes the OpenCloud API behavior a
|
||||
function of the backend rather than a contract, and it keeps the
|
||||
per-facet boilerplate cost for every new field.
|
||||
|
||||
### Option 2: Generate one backend's mapping from the other
|
||||
|
||||
Treat one backend as canonical (likely bleve, because Go types) and
|
||||
derive the other. Partial answer; it still does not help the reader
|
||||
path or the graph walker, and still leaves per-facet boilerplate in
|
||||
non-mapping code.
|
||||
|
||||
### Option 3: A struct-driven mapping (chosen)
|
||||
|
||||
Let the Go struct that represents an indexed document, together
|
||||
with a small overrides map, be the single source of truth. A
|
||||
reflection-based helper walks the struct via json tags and emits
|
||||
each backend's index mapping. The same definition drives the
|
||||
write-time path, the hit-decoding path, and the query compiler's
|
||||
case-folding rules. Any future field follows one declaration in
|
||||
one place and falls through the whole pipeline consistently.
|
||||
|
||||
## Decision Outcome
|
||||
|
||||
Adopt Option 3. The Go struct that represents an indexed document,
|
||||
together with a small overrides map, becomes the single source of
|
||||
truth for the search index. The bleve and OpenSearch index
|
||||
mappings, the write-time conversion, the hit-decoding path, and
|
||||
the query compiler's case-folding rules are all derived from that
|
||||
same definition. Drift between backends is prevented by
|
||||
construction, because there is no second place to edit.
|
||||
|
||||
The overrides surface stays small. Each entry declares one of a
|
||||
handful of things per field: a semantic type for fields whose
|
||||
intent cannot be inferred from the Go type (for example a path-
|
||||
analyzed field, a fulltext field, a geopoint field), or search-
|
||||
behavior flags (case-insensitivity, word breaking, inclusion in
|
||||
the catch-all field). Any field that needs something beyond the
|
||||
inferred defaults gets one line in the overrides map and that one
|
||||
line flows through every derived piece. Overrides are validated at
|
||||
startup so a typo fails loudly instead of silently disabling a
|
||||
setting.
|
||||
|
||||
A practical consequence of having one place to hook things: when a
|
||||
new capability is needed (a geopoint representation, a sibling
|
||||
field for a different aggregation behavior, a different analyzer
|
||||
for a class of fields, ...) it can be implemented once per backend
|
||||
in the central pipeline. After that, turning the capability on for
|
||||
a specific field is a single override entry, and both backends
|
||||
adopt it the same way. This ADR does not decide which capabilities
|
||||
to add, only that they will land in this uniform shape rather than
|
||||
through coordinated per-site edits.
|
||||
|
||||
### Facet values are indexed as case-preserving keywords
|
||||
|
||||
All facet sub-fields, meaning any leaf inside `audio`, `photo`, `image`, `location` and the facets that followed (`video`, `motionPhoto`, `livePhoto`), keep a case-preserving keyword as their stored base field on both backends. The raw value the extractor saw, or the CS3 ArbitraryMetadata string, is what lands in the index, and it is what returning, sorting and aggregations read.
|
||||
|
||||
This is the single intended semantic for facets across bleve and
|
||||
OpenSearch, and it is driven by what aggregations need.
|
||||
Aggregation buckets ("group all files by `audio.artist`", "list
|
||||
distinct `photo.cameraMake`") return bucket keys drawn from the
|
||||
indexed terms. If the indexing analyzer lowercases (OpenSearch's
|
||||
default `text + keyword` multi-field against the text leg, or a
|
||||
`lowercaseKeyword`-style analyzer), the buckets come back lower-
|
||||
cased: a distinct-artists query would answer `motörhead` and
|
||||
`queen` instead of the original display casings, and two tag
|
||||
writers using `Motörhead` versus `MOTÖRHEAD` would collapse into a
|
||||
single bucket labelled `motörhead`. For a metadata display use
|
||||
case (thumbnails, facet filters in the UI, distinct lists) that
|
||||
behavior is not what we want.
|
||||
|
||||
Searching is layered on top as exactly the strict superset the proposal reserved for later, and it shipped with the implementation: every keyword field additionally gets search-only sibling fields derived from the same definition, a `_lowercase` keyword sibling (doc values disabled; serves wildcards and `=` whole-value matches) and a `_words` text sibling (`words` analyzer: dots to spaces, unicode tokenization, lowercasing, no stemming; serves token and phrase matches). Case-insensitive, word-broken search is the default for every keyword field including facets; fields opt out per override where that is wrong: opaque ids (`ID`, `RootID`, `ParentID`, `Favorites`, `livePhoto.contentId`), the POSIX `Path`, the normalized `MimeType`, and `Content`, which is a fulltext field of its own. Aggregation buckets keep their display casing because they read the base field, never the siblings.
|
||||
|
||||
The query side derives from the same source: the shared lowering pass resolves field names case-insensitively, folds values and routes each match to the right sibling (wildcards to `_lowercase`, tokens and phrases to `_words`, `=` as a whole-value term on `_lowercase`), and both backend compilers consume that one decision. The engine parity suite pins the resulting behavior against bleve and OpenSearch, so a divergence fails CI instead of surfacing in production. The case-sensitivity alignment started in #2633 is completed by deriving both sides from the same source.
|
||||
|
||||
### Schema versioning and upgrades
|
||||
|
||||
Index names carry a schema version derived from the single `search.SchemaVersion` constant (`opencloud-resource-v4`, `bleve-v4`). On startup the service classifies the stored mapping against the code: additive changes (new fields, unchanged analyzers) are reconciled in place without a version bump, breaking changes make the service refuse to start and name the reindex steps. The upgrade path is a plain reindex (`opencloud search index --all-spaces`) into the new versioned index; older indexes stay untouched and can be deleted afterwards (services/search/MIGRATION.md). Golden mapping tests on both backends pin the rendered mappings and reuse the same classifier to tell a contributor whether a change needs only a golden regeneration or a version bump.
|
||||
|
||||
### Known trade-off
|
||||
|
||||
The write-time pipeline produces the document as a generic map via
|
||||
a json round-trip. The OpenSearch write path already does the
|
||||
equivalent today via the same json-based conversion helper, so
|
||||
that path is unchanged. The bleve write path, which previously
|
||||
handed the struct directly to bleve's reflective indexer, now goes
|
||||
through the same map-producing step and pays roughly the same
|
||||
cost. On hot paths (initial indexing of a large space) this is
|
||||
measurable but not significant; if it ever matters, a direct
|
||||
reflection walker can replace the json round-trip without changing
|
||||
any call site.
|
||||
|
||||
### Follow-ups out of scope for this ADR
|
||||
|
||||
- **WebDAV REPORT facet exposure.** The current webdav search
|
||||
endpoint renders none of the facet fields back to the client.
|
||||
This is a missing feature, not a regression of the proposal;
|
||||
its natural resolution is to let the graph-search endpoint
|
||||
(proposed in #3211) take over once graph search lands.
|
||||
- **Graph search hit conversion.** Graph search (#3211) translates
|
||||
proto hits back into libregraph DriveItems with the same
|
||||
facet-copy helper the search service uses internally.
|
||||
- **reva's PROPFIND facet listing** uses its own hand-maintained
|
||||
per-facet key lists. reva deliberately does not depend on the
|
||||
libregraph Go types, so unifying those key sets is a reva-side
|
||||
decision tracked separately.
|
||||
- **Write-path performance.** The json round-trip in the bleve
|
||||
write path is an optional optimisation target with no call-site
|
||||
impact when it lands.
|
||||
@@ -1,29 +1,28 @@
|
||||
module github.com/opencloud-eu/opencloud
|
||||
|
||||
go 1.25.0
|
||||
go 1.25.9
|
||||
|
||||
require (
|
||||
dario.cat/mergo v1.0.2
|
||||
github.com/CiscoM31/godata v1.0.11
|
||||
github.com/KimMachineGun/automemlimit v0.7.5
|
||||
github.com/KimMachineGun/automemlimit v1.0.0
|
||||
github.com/Masterminds/semver v1.5.0
|
||||
github.com/MicahParks/keyfunc/v2 v2.1.0
|
||||
github.com/Nerzal/gocloak/v13 v13.9.0
|
||||
github.com/bbalet/stopwords v1.0.0
|
||||
github.com/beevik/etree v1.6.0
|
||||
github.com/blevesearch/bleve/v2 v2.5.7
|
||||
github.com/beevik/etree v1.7.1
|
||||
github.com/blevesearch/bleve/v2 v2.6.1
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible
|
||||
github.com/coreos/go-oidc/v3 v3.18.0
|
||||
github.com/coreos/go-oidc/v3 v3.20.0
|
||||
github.com/cs3org/go-cs3apis v0.0.0-20260424072047-8d9ef7076ae9
|
||||
github.com/davidbyttow/govips/v2 v2.18.0
|
||||
github.com/dhowden/tag v0.0.0-20240417053706-3d75831295e8
|
||||
github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e
|
||||
github.com/gabriel-vasile/mimetype v1.4.13
|
||||
github.com/gabriel-vasile/mimetype v1.4.15
|
||||
github.com/ggwhite/go-masker v1.1.0
|
||||
github.com/go-chi/chi/v5 v5.2.5
|
||||
github.com/go-chi/chi/v5 v5.3.2
|
||||
github.com/go-chi/render v1.0.3
|
||||
github.com/go-jose/go-jose/v3 v3.0.5
|
||||
github.com/go-ldap/ldap/v3 v3.4.13
|
||||
github.com/go-ldap/ldap/v3 v3.4.14
|
||||
github.com/go-ldap/ldif v0.0.0-20200320164324-fd88d9b715b3
|
||||
github.com/go-micro/plugins/v4/client/grpc v1.2.1
|
||||
github.com/go-micro/plugins/v4/logger/zerolog v1.2.0
|
||||
@@ -41,78 +40,79 @@ require (
|
||||
github.com/google/go-cmp v0.7.0
|
||||
github.com/google/go-tika v0.3.1
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/gookit/config/v2 v2.2.7
|
||||
github.com/gookit/config/v2 v2.2.9
|
||||
github.com/gorilla/mux v1.8.1
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.30.0
|
||||
github.com/invopop/validation v0.8.0
|
||||
github.com/jellydator/ttlcache/v2 v2.11.1
|
||||
github.com/jellydator/ttlcache/v3 v3.4.0
|
||||
github.com/jellydator/ttlcache/v3 v3.4.1
|
||||
github.com/jinzhu/now v1.1.5
|
||||
github.com/justinas/alice v1.2.0
|
||||
github.com/kovidgoyal/imaging v1.8.20
|
||||
github.com/kovidgoyal/imaging v1.8.23
|
||||
github.com/leonelquinteros/gotext v1.7.3-0.20260422134830-b012b4ccae69
|
||||
github.com/libregraph/idm v0.5.0
|
||||
github.com/libregraph/lico v0.66.0
|
||||
github.com/libregraph/lico v0.67.0
|
||||
github.com/mna/pigeon v1.3.0
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
|
||||
github.com/nats-io/nats-server/v2 v2.14.0
|
||||
github.com/nats-io/nats.go v1.51.0
|
||||
github.com/nats-io/nats-server/v2 v2.14.5
|
||||
github.com/nats-io/nats.go v1.53.1
|
||||
github.com/olekukonko/tablewriter v1.1.4
|
||||
github.com/onsi/ginkgo v1.16.5
|
||||
github.com/onsi/ginkgo/v2 v2.28.3
|
||||
github.com/onsi/gomega v1.40.0
|
||||
github.com/open-policy-agent/opa v1.15.2
|
||||
github.com/onsi/ginkgo/v2 v2.32.1
|
||||
github.com/onsi/gomega v1.42.1
|
||||
github.com/open-policy-agent/opa v1.19.1
|
||||
github.com/opencloud-eu/icap-client v0.0.0-20250930132611-28a2afe62d89
|
||||
github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20260310090739-853d972b282d
|
||||
github.com/opencloud-eu/reva/v2 v2.46.3-0.20260610093751-a33d8108dd91
|
||||
github.com/opensearch-project/opensearch-go/v4 v4.6.0
|
||||
github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20260902170011-45af3945a067
|
||||
github.com/opencloud-eu/reva/v2 v2.49.1-0.20260903122659-26f34ec05774
|
||||
github.com/opensearch-project/opensearch-go/v4 v4.7.3
|
||||
github.com/orcaman/concurrent-map v1.0.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/pkg/xattr v0.4.12
|
||||
github.com/prometheus/client_golang v1.23.2
|
||||
github.com/prometheus/client_golang v1.24.1
|
||||
github.com/prometheus/client_model v0.6.2
|
||||
github.com/r3labs/sse/v2 v2.10.0
|
||||
github.com/riandyrn/otelchi v0.12.3
|
||||
github.com/rogpeppe/go-internal v1.14.1
|
||||
github.com/rogpeppe/go-internal v1.16.0
|
||||
github.com/rs/cors v1.11.1
|
||||
github.com/rs/zerolog v1.35.0
|
||||
github.com/sirupsen/logrus v1.9.4
|
||||
github.com/rs/zerolog v1.35.1
|
||||
github.com/shamaton/msgpack/v2 v2.4.1
|
||||
github.com/sirupsen/logrus v1.10.1
|
||||
github.com/spf13/afero v1.15.0
|
||||
github.com/spf13/cobra v1.10.2
|
||||
github.com/spf13/pflag v1.0.10
|
||||
github.com/spf13/viper v1.21.0
|
||||
github.com/stretchr/testify v1.11.1
|
||||
github.com/stretchr/testify v1.12.1
|
||||
github.com/test-go/testify v1.1.4
|
||||
github.com/testcontainers/testcontainers-go v0.42.0
|
||||
github.com/testcontainers/testcontainers-go/modules/opensearch v0.42.0
|
||||
github.com/theckman/yacspin v0.13.12
|
||||
github.com/testcontainers/testcontainers-go v0.44.0
|
||||
github.com/testcontainers/testcontainers-go/modules/opensearch v0.44.0
|
||||
github.com/thejerf/suture/v4 v4.0.6
|
||||
github.com/tidwall/gjson v1.19.0
|
||||
github.com/tidwall/sjson v1.2.5
|
||||
github.com/tus/tusd/v2 v2.9.2
|
||||
github.com/tus/tusd/v2 v2.10.0
|
||||
github.com/unrolled/secure v1.16.0
|
||||
github.com/vmihailenco/msgpack/v5 v5.4.1
|
||||
github.com/xhit/go-simple-mail/v2 v2.16.0
|
||||
go-micro.dev/v4 v4.11.0
|
||||
go.etcd.io/bbolt v1.4.3
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.69.0
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0
|
||||
go.opentelemetry.io/contrib/zpages v0.68.0
|
||||
go.opentelemetry.io/otel v1.44.0
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.44.0
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.43.0
|
||||
go.opentelemetry.io/otel/sdk v1.44.0
|
||||
go.opentelemetry.io/otel/trace v1.44.0
|
||||
golang.org/x/crypto v0.52.0
|
||||
go.etcd.io/bbolt v1.5.0
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.70.0
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.70.0
|
||||
go.opentelemetry.io/contrib/zpages v0.71.0
|
||||
go.opentelemetry.io/otel v1.46.0
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.45.0
|
||||
go.opentelemetry.io/otel/sdk v1.46.0
|
||||
go.opentelemetry.io/otel/trace v1.46.0
|
||||
golang.org/x/crypto v0.55.0
|
||||
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f
|
||||
golang.org/x/image v0.40.0
|
||||
golang.org/x/net v0.55.0
|
||||
golang.org/x/image v0.45.0
|
||||
golang.org/x/net v0.58.0
|
||||
golang.org/x/oauth2 v0.36.0
|
||||
golang.org/x/sync v0.20.0
|
||||
golang.org/x/term v0.43.0
|
||||
golang.org/x/text v0.37.0
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa
|
||||
google.golang.org/grpc v1.81.1
|
||||
google.golang.org/protobuf v1.36.11
|
||||
golang.org/x/sync v0.22.0
|
||||
golang.org/x/term v0.45.0
|
||||
golang.org/x/text v0.41.0
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d
|
||||
google.golang.org/grpc v1.83.2
|
||||
google.golang.org/protobuf v1.36.12
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
gotest.tools/v3 v3.5.2
|
||||
@@ -126,47 +126,48 @@ require (
|
||||
github.com/Azure/go-ntlmssp v0.1.1 // indirect
|
||||
github.com/BurntSushi/toml v1.6.0 // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.4.0 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.5.0 // indirect
|
||||
github.com/Masterminds/sprig v2.22.0+incompatible // indirect
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/ProtonMail/go-crypto v1.1.6 // indirect
|
||||
github.com/RoaringBitmap/roaring/v2 v2.4.5 // indirect
|
||||
github.com/RoaringBitmap/roaring/v2 v2.14.5 // indirect
|
||||
github.com/agnivade/levenshtein v1.2.1 // indirect
|
||||
github.com/ajg/form v1.5.1 // indirect
|
||||
github.com/alexedwards/argon2id v1.0.0 // indirect
|
||||
github.com/amoghe/go-crypt v0.0.0-20220222110647-20eada5f5964 // indirect
|
||||
github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op // indirect
|
||||
github.com/antithesishq/antithesis-sdk-go v0.7.2 // indirect
|
||||
github.com/armon/go-radix v1.0.0 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bitly/go-simplejson v0.5.0 // indirect
|
||||
github.com/bits-and-blooms/bitset v1.22.0 // indirect
|
||||
github.com/blevesearch/bleve_index_api v1.2.11 // indirect
|
||||
github.com/blevesearch/geo v0.2.4 // indirect
|
||||
github.com/blevesearch/go-faiss v1.0.26 // indirect
|
||||
github.com/bits-and-blooms/bitset v1.24.2 // indirect
|
||||
github.com/blevesearch/bleve_index_api v1.4.1 // indirect
|
||||
github.com/blevesearch/geo v0.2.6 // indirect
|
||||
github.com/blevesearch/go-faiss v1.1.5 // indirect
|
||||
github.com/blevesearch/go-porterstemmer v1.0.3 // indirect
|
||||
github.com/blevesearch/gtreap v0.1.1 // indirect
|
||||
github.com/blevesearch/mmap-go v1.0.4 // indirect
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.3.13 // indirect
|
||||
github.com/blevesearch/mmap-go v1.2.0 // indirect
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.4.10 // indirect
|
||||
github.com/blevesearch/segment v0.9.1 // indirect
|
||||
github.com/blevesearch/snowballstem v0.9.0 // indirect
|
||||
github.com/blevesearch/upsidedown_store_api v1.0.2 // indirect
|
||||
github.com/blevesearch/vellum v1.1.0 // indirect
|
||||
github.com/blevesearch/zapx/v11 v11.4.2 // indirect
|
||||
github.com/blevesearch/zapx/v12 v12.4.2 // indirect
|
||||
github.com/blevesearch/zapx/v13 v13.4.2 // indirect
|
||||
github.com/blevesearch/zapx/v14 v14.4.2 // indirect
|
||||
github.com/blevesearch/zapx/v15 v15.4.2 // indirect
|
||||
github.com/blevesearch/zapx/v16 v16.2.8 // indirect
|
||||
github.com/blevesearch/vellum v1.2.0 // indirect
|
||||
github.com/blevesearch/zapx/v11 v11.4.3 // indirect
|
||||
github.com/blevesearch/zapx/v12 v12.4.3 // indirect
|
||||
github.com/blevesearch/zapx/v13 v13.4.3 // indirect
|
||||
github.com/blevesearch/zapx/v14 v14.4.3 // indirect
|
||||
github.com/blevesearch/zapx/v15 v15.4.3 // indirect
|
||||
github.com/blevesearch/zapx/v16 v16.3.4 // indirect
|
||||
github.com/blevesearch/zapx/v17 v17.2.3 // indirect
|
||||
github.com/bluele/gcache v0.0.2 // indirect
|
||||
github.com/bombsimon/logrusr/v3 v3.1.0 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
|
||||
github.com/ceph/go-ceph v0.39.0 // indirect
|
||||
github.com/ceph/go-ceph v0.40.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/cevaris/ordered_map v0.0.0-20190319150403-3adeae072e73 // indirect
|
||||
github.com/clipperhouse/displaywidth v0.10.0 // indirect
|
||||
github.com/clipperhouse/uax29/v2 v2.6.0 // indirect
|
||||
github.com/clipperhouse/displaywidth v0.11.0 // indirect
|
||||
github.com/clipperhouse/uax29/v2 v2.7.0 // indirect
|
||||
github.com/cloudflare/circl v1.6.3 // indirect
|
||||
github.com/containerd/errdefs v1.0.0 // indirect
|
||||
github.com/containerd/errdefs/pkg v0.3.0 // indirect
|
||||
@@ -182,40 +183,40 @@ require (
|
||||
github.com/cyphar/filepath-securejoin v0.6.1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/deckarep/golang-set v1.8.0 // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.1 // indirect
|
||||
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect
|
||||
github.com/dgraph-io/ristretto v0.2.0 // indirect
|
||||
github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/distribution/reference v0.6.0 // indirect
|
||||
github.com/dlclark/regexp2 v1.4.0 // indirect
|
||||
github.com/docker/go-connections v0.6.0 // indirect
|
||||
github.com/dlclark/regexp2 v1.12.0 // indirect
|
||||
github.com/docker/go-connections v0.7.0 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/ebitengine/purego v0.10.0 // indirect
|
||||
github.com/ebitengine/purego v0.10.1 // indirect
|
||||
github.com/egirna/icap v0.0.0-20181108071049-d5ee18bd70bc // indirect
|
||||
github.com/emirpasic/gods v1.18.1 // indirect
|
||||
github.com/emvi/iso-639-1 v1.1.1 // indirect
|
||||
github.com/evanphx/json-patch/v5 v5.5.0 // indirect
|
||||
github.com/fatih/color v1.18.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||
github.com/fatih/color v1.19.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.1.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.10.1 // indirect
|
||||
github.com/gdexlab/go-render v1.0.1 // indirect
|
||||
github.com/go-acme/lego/v4 v4.4.0 // indirect
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.8 // indirect
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||
github.com/go-git/go-billy/v5 v5.9.0 // indirect
|
||||
github.com/go-git/go-git/v5 v5.19.1 // indirect
|
||||
github.com/go-ini/ini v1.67.0 // indirect
|
||||
github.com/go-git/go-git/v5 v5.19.2 // indirect
|
||||
github.com/go-jose/go-jose/v3 v3.0.5 // indirect
|
||||
github.com/go-jose/go-jose/v4 v4.1.4 // indirect
|
||||
github.com/go-kit/log v0.2.1 // indirect
|
||||
github.com/go-logfmt/logfmt v0.5.1 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/logr v1.4.4 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-micro/plugins/v4/events/natsjs v1.2.2 // indirect
|
||||
github.com/go-micro/plugins/v4/store/nats-js v1.2.1 // indirect
|
||||
github.com/go-micro/plugins/v4/store/redis v1.2.1 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-redis/redis/v8 v8.11.5 // indirect
|
||||
@@ -227,19 +228,18 @@ require (
|
||||
github.com/gobwas/httphead v0.1.0 // indirect
|
||||
github.com/gobwas/pool v0.2.1 // indirect
|
||||
github.com/gobwas/ws v1.2.1 // indirect
|
||||
github.com/goccy/go-json v0.10.5 // indirect
|
||||
github.com/goccy/go-yaml v1.18.0 // indirect
|
||||
github.com/goccy/go-json v0.10.6 // indirect
|
||||
github.com/goccy/go-yaml v1.19.2 // indirect
|
||||
github.com/gofrs/flock v0.13.0 // indirect
|
||||
github.com/gofrs/uuid v4.4.0+incompatible // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/golang/snappy v1.0.0 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/go-tpm v0.9.8 // indirect
|
||||
github.com/google/pprof v0.0.0-20260402051712-545e8a4df936 // indirect
|
||||
github.com/google/renameio/v2 v2.0.2 // indirect
|
||||
github.com/gookit/goutil v0.7.4 // indirect
|
||||
github.com/gookit/goutil v0.8.0 // indirect
|
||||
github.com/gorilla/handlers v1.5.1 // indirect
|
||||
github.com/gorilla/schema v1.4.1 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect
|
||||
@@ -256,29 +256,29 @@ require (
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/juliangruber/go-intersect v1.1.0 // indirect
|
||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||
github.com/klauspost/compress v1.18.5 // indirect
|
||||
github.com/klauspost/compress v1.19.2 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||
github.com/klauspost/crc32 v1.3.0 // indirect
|
||||
github.com/kovidgoyal/go-parallel v1.1.1 // indirect
|
||||
github.com/kovidgoyal/go-shm v1.0.0 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/lestrrat-go/blackmagic v1.0.4 // indirect
|
||||
github.com/lestrrat-go/dsig v1.0.0 // indirect
|
||||
github.com/lestrrat-go/dsig v1.2.1 // indirect
|
||||
github.com/lestrrat-go/dsig-secp256k1 v1.0.0 // indirect
|
||||
github.com/lestrrat-go/httpcc v1.0.1 // indirect
|
||||
github.com/lestrrat-go/httprc/v3 v3.0.2 // indirect
|
||||
github.com/lestrrat-go/jwx/v3 v3.0.13 // indirect
|
||||
github.com/lestrrat-go/httprc/v3 v3.0.5 // indirect
|
||||
github.com/lestrrat-go/jwx/v3 v3.1.1 // indirect
|
||||
github.com/lestrrat-go/option/v2 v2.0.0 // indirect
|
||||
github.com/libregraph/oidc-go v1.1.0 // indirect
|
||||
github.com/longsleep/go-metrics v1.0.0 // indirect
|
||||
github.com/longsleep/rndm v1.2.0 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e // indirect
|
||||
github.com/magiconair/properties v1.8.10 // indirect
|
||||
github.com/mattermost/xml-roundtrip-validator v0.1.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.19 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.42 // indirect
|
||||
github.com/mattn/go-colorable v0.1.15 // indirect
|
||||
github.com/mattn/go-isatty v0.0.22 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.24 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.49 // indirect
|
||||
github.com/maxymania/go-system v0.0.0-20170110133659-647cc364bf0b // indirect
|
||||
github.com/mendsley/gojwk v0.0.0-20141217222730-4d5ec6e58103 // indirect
|
||||
github.com/miekg/dns v1.1.68 // indirect
|
||||
@@ -286,15 +286,15 @@ require (
|
||||
github.com/minio/crc64nvme v1.1.1 // indirect
|
||||
github.com/minio/highwayhash v1.0.4 // indirect
|
||||
github.com/minio/md5-simd v1.1.2 // indirect
|
||||
github.com/minio/minio-go/v7 v7.1.0 // indirect
|
||||
github.com/minio/minio-go/v7 v7.2.1 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||
github.com/moby/go-archive v0.2.0 // indirect
|
||||
github.com/moby/moby/api v1.54.1 // indirect
|
||||
github.com/moby/moby/client v0.4.0 // indirect
|
||||
github.com/moby/moby/api v1.55.0 // indirect
|
||||
github.com/moby/moby/client v0.5.0 // indirect
|
||||
github.com/moby/patternmatcher v0.6.1 // indirect
|
||||
github.com/moby/sys/sequential v0.6.0 // indirect
|
||||
github.com/moby/sys/sequential v0.7.0 // indirect
|
||||
github.com/moby/sys/user v0.4.0 // indirect
|
||||
github.com/moby/sys/userns v0.1.0 // indirect
|
||||
github.com/moby/term v0.5.2 // indirect
|
||||
@@ -302,8 +302,8 @@ require (
|
||||
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
|
||||
github.com/mschoch/smat v0.2.0 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/nats-io/jwt/v2 v2.8.1 // indirect
|
||||
github.com/nats-io/nkeys v0.4.15 // indirect
|
||||
github.com/nats-io/jwt/v2 v2.8.2 // indirect
|
||||
github.com/nats-io/nkeys v0.4.16 // indirect
|
||||
github.com/nats-io/nuid v1.0.1 // indirect
|
||||
github.com/nxadm/tail v1.4.8 // indirect
|
||||
github.com/oklog/run v1.2.0 // indirect
|
||||
@@ -317,17 +317,15 @@ require (
|
||||
github.com/pablodz/inotifywaitgo v0.0.12 // indirect
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.3.1 // indirect
|
||||
github.com/philhofer/fwd v1.2.0 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.15 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.26 // indirect
|
||||
github.com/pjbgf/sha1cd v0.6.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
|
||||
github.com/pquerna/cachecontrol v0.2.0 // indirect
|
||||
github.com/prometheus/alertmanager v0.31.1 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.67.5 // indirect
|
||||
github.com/prometheus/procfs v0.17.0 // indirect
|
||||
github.com/prometheus/common v0.70.1 // indirect
|
||||
github.com/prometheus/procfs v0.21.1 // indirect
|
||||
github.com/prometheus/statsd_exporter v0.22.8 // indirect
|
||||
github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9 // indirect
|
||||
github.com/rs/xid v1.6.0 // indirect
|
||||
@@ -339,16 +337,13 @@ require (
|
||||
github.com/samber/slog-common v0.21.0 // indirect
|
||||
github.com/samber/slog-zerolog/v2 v2.9.2 // indirect
|
||||
github.com/segmentio/asm v1.2.1 // indirect
|
||||
github.com/segmentio/kafka-go v0.4.50 // indirect
|
||||
github.com/segmentio/kafka-go v0.4.51 // indirect
|
||||
github.com/segmentio/ksuid v1.0.4 // indirect
|
||||
github.com/sercand/kuberesolver/v5 v5.1.1 // indirect
|
||||
github.com/sergi/go-diff v1.4.0 // indirect
|
||||
github.com/sethvargo/go-diceware v0.5.0 // indirect
|
||||
github.com/sethvargo/go-password v0.3.1 // indirect
|
||||
github.com/shamaton/msgpack/v2 v2.4.1 // indirect
|
||||
github.com/shirou/gopsutil/v4 v4.26.3 // indirect
|
||||
github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c // indirect
|
||||
github.com/shurcooL/vfsgen v0.0.0-20230704071429-0000e147ea92 // indirect
|
||||
github.com/sethvargo/go-diceware v0.6.0 // indirect
|
||||
github.com/sethvargo/go-password v0.4.0 // indirect
|
||||
github.com/shirou/gopsutil/v4 v4.26.6 // indirect
|
||||
github.com/skeema/knownhosts v1.3.1 // indirect
|
||||
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
|
||||
github.com/spacewander/go-suffix-tree v0.0.0-20191010040751-0865e368c784 // indirect
|
||||
@@ -360,13 +355,13 @@ require (
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.1 // indirect
|
||||
github.com/tinylib/msgp v1.6.1 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.16 // indirect
|
||||
github.com/tklauser/numcpus v0.11.0 // indirect
|
||||
github.com/tklauser/go-sysconf v0.4.0 // indirect
|
||||
github.com/tklauser/numcpus v0.12.0 // indirect
|
||||
github.com/toorop/go-dkim v0.0.0-20201103131630-e1cd1a0a5208 // indirect
|
||||
github.com/trustelem/zxcvbn v1.0.1 // indirect
|
||||
github.com/urfave/cli/v2 v2.27.7 // indirect
|
||||
github.com/valyala/fastjson v1.6.7 // indirect
|
||||
github.com/vektah/gqlparser/v2 v2.5.32 // indirect
|
||||
github.com/valyala/fastjson v1.6.10 // indirect
|
||||
github.com/vektah/gqlparser/v2 v2.5.36 // indirect
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||
github.com/wk8/go-ordered-map v1.0.0 // indirect
|
||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||
@@ -376,25 +371,26 @@ require (
|
||||
github.com/yashtewari/glob-intersection v0.2.0 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||
github.com/zeebo/xxh3 v1.1.0 // indirect
|
||||
go.etcd.io/etcd/api/v3 v3.6.11 // indirect
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.6.11 // indirect
|
||||
go.etcd.io/etcd/client/v3 v3.6.11 // indirect
|
||||
go.etcd.io/etcd/api/v3 v3.6.13 // indirect
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.6.13 // indirect
|
||||
go.etcd.io/etcd/client/v3 v3.6.13 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.44.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.44.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.10.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.45.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.46.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.11.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/mod v0.35.0 // indirect
|
||||
golang.org/x/sys v0.45.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.4 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.5 // indirect
|
||||
golang.org/x/mod v0.38.0 // indirect
|
||||
golang.org/x/sys v0.47.0 // indirect
|
||||
golang.org/x/time v0.15.0 // indirect
|
||||
golang.org/x/tools v0.44.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20260128011058-8636f8732409 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa // indirect
|
||||
golang.org/x/tools v0.48.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20260319201613-d00831a3d3e7 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d // indirect
|
||||
gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect
|
||||
gopkg.in/ini.v1 v1.67.3 // indirect
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
sigs.k8s.io/yaml v1.6.0 // indirect
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package eventstest
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
|
||||
"github.com/google/uuid"
|
||||
|
||||
rev "github.com/opencloud-eu/reva/v2/pkg/events"
|
||||
microevents "go-micro.dev/v4/events"
|
||||
)
|
||||
|
||||
func NewTestBus() TestBus {
|
||||
return TestBus(make(chan rev.Event))
|
||||
}
|
||||
|
||||
type TestBus chan rev.Event
|
||||
|
||||
func (tb TestBus) Consume(_ string, _ ...microevents.ConsumeOption) (<-chan microevents.Event, error) {
|
||||
ch := make(chan microevents.Event)
|
||||
go func() {
|
||||
for ev := range tb {
|
||||
b, _ := json.Marshal(ev.Event)
|
||||
ch <- microevents.Event{
|
||||
Payload: b,
|
||||
Metadata: map[string]string{
|
||||
rev.MetadatakeyEventID: ev.ID,
|
||||
rev.MetadatakeyEventType: ev.Type,
|
||||
},
|
||||
}
|
||||
}
|
||||
}()
|
||||
return ch, nil
|
||||
}
|
||||
|
||||
func (tb TestBus) Publish(e any) string {
|
||||
ev := rev.Event{
|
||||
ID: uuid.New().String(),
|
||||
Type: reflect.TypeOf(e).String(),
|
||||
Event: e,
|
||||
}
|
||||
tb <- ev
|
||||
return ev.ID
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
package metricstest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// copied and adapted from Prometheus testutil.ToFloat64(), since we don't import that package
|
||||
func collect(c prometheus.Collector) []prometheus.Metric {
|
||||
result := []prometheus.Metric{}
|
||||
ch := make(chan prometheus.Metric)
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
for m := range ch {
|
||||
result = append(result, m)
|
||||
}
|
||||
close(done)
|
||||
}()
|
||||
c.Collect(ch)
|
||||
close(ch)
|
||||
<-done
|
||||
return result
|
||||
}
|
||||
|
||||
func RequireIsNotSet(t require.TestingT, c prometheus.Collector, msgAndArgs ...any) {
|
||||
if h, ok := t.(interface{ Helper() }); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if !IsNotSet(t, c, msgAndArgs) {
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
|
||||
func IsNotSet(t assert.TestingT, c prometheus.Collector, msgAndArgs ...any) bool {
|
||||
if h, ok := t.(interface{ Helper() }); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
m := collect(c)
|
||||
if len(m) > 0 {
|
||||
return assert.Fail(t, "Metric exists while expected to not exist", msgAndArgs)
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func RequireEqual(t require.TestingT, expected float64, c prometheus.Collector, msgAndArgs ...any) {
|
||||
if h, ok := t.(interface{ Helper() }); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if !Equal(t, expected, c, msgAndArgs) {
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
|
||||
// copied and adapted from Prometheus testutil.ToFloat64(), since we don't import that package
|
||||
func Equal(t assert.TestingT, expected float64, c prometheus.Collector, msgAndArgs ...any) bool {
|
||||
if h, ok := t.(interface{ Helper() }); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
m := collect(c)
|
||||
if !assert.Len(t, m, 1, msgAndArgs...) {
|
||||
return false
|
||||
}
|
||||
pb := &dto.Metric{}
|
||||
err := m[0].Write(pb)
|
||||
if !assert.NoError(t, err, msgAndArgs...) {
|
||||
return false
|
||||
}
|
||||
if pb.Gauge != nil {
|
||||
return assert.Equal(t, expected, pb.Gauge.GetValue(), msgAndArgs...)
|
||||
} else if pb.Counter != nil {
|
||||
return assert.Equal(t, expected, pb.Counter.GetValue(), msgAndArgs...)
|
||||
} else if pb.Untyped != nil {
|
||||
return assert.Equal(t, expected, pb.Untyped.GetValue(), msgAndArgs...)
|
||||
} else {
|
||||
return assert.Fail(t, fmt.Sprintf("collected a non-gauge/counter/untyped metric: %s", pb), msgAndArgs...)
|
||||
}
|
||||
}
|
||||
|
||||
func RequireEqualWithLabels(t require.TestingT, expectedValue float64, expectedLabels map[string]string, c prometheus.Collector, msgAndArgs ...any) {
|
||||
if h, ok := t.(interface{ Helper() }); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if !EqualWithLabels(t, expectedValue, expectedLabels, c, msgAndArgs) {
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
|
||||
func EqualWithLabels(t assert.TestingT, expectedValue float64, expectedLabels map[string]string, c prometheus.Collector, msgAndArgs ...any) bool {
|
||||
if h, ok := t.(interface{ Helper() }); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
m := collect(c)
|
||||
if !assert.Len(t, m, 1, "collected %d metrics instead of exactly 1", len(m)) {
|
||||
return false
|
||||
}
|
||||
pb := &dto.Metric{}
|
||||
err := m[0].Write(pb)
|
||||
if !assert.NoError(t, err) {
|
||||
return false
|
||||
}
|
||||
if pb.Gauge != nil {
|
||||
if !assert.Equal(t, expectedValue, pb.Gauge.GetValue()) {
|
||||
return false
|
||||
}
|
||||
} else if pb.Counter != nil {
|
||||
if !assert.Equal(t, expectedValue, pb.Counter.GetValue()) {
|
||||
return false
|
||||
}
|
||||
} else if pb.Untyped != nil {
|
||||
if !assert.Equal(t, expectedValue, pb.Untyped.GetValue()) {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
return assert.Fail(t, "collected a non-gauge/counter/untyped metric: %s", pb)
|
||||
}
|
||||
|
||||
if !assert.NotNil(t, pb.Label) {
|
||||
return false
|
||||
}
|
||||
actualLabels := map[string]string{}
|
||||
for _, label := range pb.Label {
|
||||
if !assert.NotNil(t, label) {
|
||||
return false
|
||||
}
|
||||
if !assert.NotNil(t, label.Name) {
|
||||
return false
|
||||
}
|
||||
if !assert.NotNil(t, label.Value) {
|
||||
return false
|
||||
}
|
||||
actualLabels[*label.Name] = *label.Value
|
||||
}
|
||||
return assert.Equal(t, expectedLabels, actualLabels, msgAndArgs)
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
[env]
|
||||
GO_VERSION = "{{ exec(command='./.mise-go-version.sh') }}"
|
||||
|
||||
[tools]
|
||||
go = "{{ env.GO_VERSION }}"
|
||||
node = "24"
|
||||
pnpm = "11.1.3"
|
||||
"go:github.com/go-delve/delve/cmd/dlv" = "1.27.1"
|
||||
"aqua:nats-io/natscli" = "0.4.0"
|
||||
k6 = "2.2.0"
|
||||
ginkgo = "latest"
|
||||
|
||||
[tasks.build]
|
||||
description = "build"
|
||||
run = "make -C opencloud build"
|
||||
|
||||
[tasks."build:debug"]
|
||||
description = "build with debug symbols"
|
||||
run = "make -C opencloud build-debug"
|
||||
|
||||
[tasks."docker:build"]
|
||||
description = "docker image opencloudeu/opencloud:dev"
|
||||
run = "make -C opencloud dev-docker"
|
||||
|
||||
[tasks."docker:build:multiarch"]
|
||||
description = "docker image for amd64 + arm64"
|
||||
depends = ["gen"]
|
||||
run = "make -C opencloud dev-docker-multiarch"
|
||||
|
||||
[tasks."docker:build:debug"]
|
||||
description = "docker image with delve"
|
||||
run = "make -C opencloud debug-docker"
|
||||
|
||||
[tasks.serve]
|
||||
description = "start the server"
|
||||
depends = ["build"]
|
||||
run = "opencloud/bin/opencloud server"
|
||||
|
||||
[tasks."serve:init"]
|
||||
description = "create the local config"
|
||||
depends = ["build"]
|
||||
run = "opencloud/bin/opencloud init"
|
||||
|
||||
[tasks."serve:debug"]
|
||||
description = "start the server under delve"
|
||||
depends = ["build:debug"]
|
||||
run = "dlv exec opencloud/bin/opencloud-debug -- server"
|
||||
|
||||
[tasks.test]
|
||||
description = "go test"
|
||||
run = "go test -tags disable_crypt ./..."
|
||||
|
||||
[tasks."test:changed"]
|
||||
description = "go test, changed packages"
|
||||
run = """
|
||||
base=$(git rev-parse --abbrev-ref --symbolic-full-name '@{u}' 2>/dev/null || echo origin/main)
|
||||
files=$(git diff --name-only --diff-filter=ACM $(git merge-base "$base" HEAD) -- '*.go' | grep -v vendor/ || true)
|
||||
[ -n "$files" ] || exit 0
|
||||
go test -tags disable_crypt $(echo "$files" | xargs -n1 dirname | sort -u | sed 's|^|./|')
|
||||
"""
|
||||
|
||||
[tasks."test:race"]
|
||||
description = "go test + race"
|
||||
run = "go test -race -tags disable_crypt ./..."
|
||||
|
||||
[tasks."test:coverage"]
|
||||
description = "go test + coverage"
|
||||
run = ["make test", "make go-coverage"]
|
||||
|
||||
[tasks.check]
|
||||
description = "all checks"
|
||||
depends = ["check:fmt", "check:lint", "check:vendor", "check:env-vars", "test"]
|
||||
|
||||
[tasks."check:fmt"]
|
||||
description = "gofmt"
|
||||
run = """
|
||||
base=$(git rev-parse --abbrev-ref --symbolic-full-name '@{u}' 2>/dev/null || echo origin/main)
|
||||
files=$(git diff --name-only --diff-filter=ACM $(git merge-base "$base" HEAD) -- '*.go' | grep -v vendor/ || true)
|
||||
[ -n "$files" ] || exit 0
|
||||
out=$(gofmt -s -l $files)
|
||||
[ -z "$out" ] || { echo "$out"; exit 1; }
|
||||
"""
|
||||
|
||||
[tasks."check:lint"]
|
||||
description = "golangci-lint"
|
||||
run = """
|
||||
set -e
|
||||
base=$(git rev-parse --abbrev-ref --symbolic-full-name '@{u}' 2>/dev/null || echo origin/main)
|
||||
gobin=$(go env GOBIN)
|
||||
[ -n "$gobin" ] || gobin="$(go env GOPATH)/bin"
|
||||
bin="$gobin/golangci-lint-$(awk '/golangci-lint v/ {print $3}' .bingo/golangci-lint.mod)"
|
||||
[ -x "$bin" ] || make -s golangci-lint >/dev/null
|
||||
exec "$bin" run --modules-download-mode vendor --timeout 15m0s --new-from-merge-base "$base"
|
||||
"""
|
||||
|
||||
[tasks."check:vendor"]
|
||||
description = "vendor matches go.mod"
|
||||
run = "GOWORK=off go list -mod=vendor ./... >/dev/null"
|
||||
|
||||
[tasks."check:env-vars"]
|
||||
description = "env var annotations"
|
||||
run = "make check-env-var-annotations"
|
||||
|
||||
[tasks.fix]
|
||||
description = "gofmt + lint fixes"
|
||||
run = [{ task = "fix:fmt" }, { task = "fix:lint" }]
|
||||
|
||||
[tasks."fix:fmt"]
|
||||
description = "gofmt -w"
|
||||
run = """
|
||||
base=$(git rev-parse --abbrev-ref --symbolic-full-name '@{u}' 2>/dev/null || echo origin/main)
|
||||
files=$(git diff --name-only --diff-filter=ACM $(git merge-base "$base" HEAD) -- '*.go' | grep -v vendor/ || true)
|
||||
[ -z "$files" ] || gofmt -s -w $files
|
||||
"""
|
||||
|
||||
[tasks."fix:lint"]
|
||||
description = "golangci-lint --fix"
|
||||
run = "make golangci-lint-fix"
|
||||
|
||||
[tasks."pre:commit"]
|
||||
description = "before commit"
|
||||
run = [{ task = "fix:fmt" }, { task = "check:lint" }, { task = "test:changed" }]
|
||||
|
||||
[tasks."pre:push"]
|
||||
description = "before push"
|
||||
run = [{ task = "tidy" }, { task = "fix:fmt" }, { task = "check" }]
|
||||
|
||||
[tasks.gen]
|
||||
description = "assets & mocks"
|
||||
run = "make generate"
|
||||
|
||||
[tasks."gen:protobuf"]
|
||||
description = "protobuf"
|
||||
run = "make protobuf"
|
||||
|
||||
[tasks.tidy]
|
||||
description = "tidy + vendor"
|
||||
run = ["GOWORK=off go mod tidy", "GOWORK=off go mod vendor"]
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM golang:alpine3.23 AS build
|
||||
FROM quay.io/opencloudeu/golang-ci:1.25 AS build
|
||||
ARG TARGETOS
|
||||
ARG TARGETARCH
|
||||
ARG VERSION
|
||||
@@ -6,16 +6,17 @@ ARG STRING
|
||||
ARG EDITION="dev"
|
||||
ARG SRCDIR
|
||||
|
||||
RUN apk add bash make git curl gcc musl-dev libc-dev binutils-gold inotify-tools vips-dev
|
||||
|
||||
WORKDIR /build
|
||||
RUN --mount=type=bind,target=/build,rw \
|
||||
--mount=type=cache,target=/go/pkg/mod \
|
||||
--mount=type=cache,target=/root/.cache \
|
||||
GOOS="${TARGETOS:-linux}" GOARCH="${TARGETARCH:-amd64}" ; \
|
||||
make -C ${SRCDIR:-.}/opencloud release-linux-docker-${TARGETARCH} ENABLE_VIPS=true DIST=/dist
|
||||
make -C ${SRCDIR:-.}/opencloud release-linux-docker-${TARGETARCH} \
|
||||
ENABLE_VIPS=true DIST=/dist \
|
||||
VERSION="${VERSION}" EDITION="${EDITION}" \
|
||||
${STRING:+STRING="${STRING}"}
|
||||
|
||||
FROM alpine:3.23
|
||||
FROM alpine:3.24
|
||||
ARG VERSION
|
||||
ARG REVISION
|
||||
ARG TARGETOS
|
||||
|
||||
+273
-429
@@ -1,17 +1,16 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/opencloud-eu/opencloud/opencloud/pkg/register"
|
||||
"github.com/opencloud-eu/opencloud/pkg/config"
|
||||
"github.com/opencloud-eu/opencloud/pkg/config/configlog"
|
||||
"github.com/opencloud-eu/opencloud/pkg/config/parser"
|
||||
"github.com/opencloud-eu/opencloud/pkg/x/path/filepathx"
|
||||
storageUsersParser "github.com/opencloud-eu/opencloud/services/storage-users/pkg/config/parser"
|
||||
"github.com/opencloud-eu/opencloud/services/storage-users/pkg/event"
|
||||
"github.com/opencloud-eu/opencloud/services/storage-users/pkg/revaconfig"
|
||||
@@ -19,26 +18,10 @@ import (
|
||||
"github.com/opencloud-eu/reva/v2/pkg/storage/fs/posix/ignore"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/storage/fs/posix/options"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/storage/fs/registry"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/storage/pkg/decomposedfs/metadata/prefixes"
|
||||
|
||||
"github.com/pkg/xattr"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/theckman/yacspin"
|
||||
"github.com/vmihailenco/msgpack/v5"
|
||||
)
|
||||
|
||||
// Define the names of the extended attributes we are working with.
|
||||
const (
|
||||
parentIDAttrName = "user.oc.parentid"
|
||||
idAttrName = "user.oc.id"
|
||||
spaceIDAttrName = "user.oc.space.id"
|
||||
ownerIDAttrName = "user.oc.owner.id"
|
||||
)
|
||||
|
||||
var (
|
||||
spinner *yacspin.Spinner
|
||||
restartRequired = false
|
||||
ignorer *ignore.Ignorer
|
||||
)
|
||||
|
||||
type IDCacher interface {
|
||||
@@ -72,11 +55,23 @@ func init() {
|
||||
|
||||
// scanCmd performs a posixfs id cache warmup scan
|
||||
func scanCmd(ocCfg *config.Config) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "scan",
|
||||
scanCmd := &cobra.Command{
|
||||
Use: "scan [path ...]",
|
||||
Short: "Perform a filesystem scan and update the ID and filemetadata cache",
|
||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
Long: `Perform a filesystem scan and update the ID and filemetadata cache.
|
||||
|
||||
You can specify one or more paths to limit the scope of the scan.
|
||||
If no path is provided, the whole storage is checked, starting at the storage root directory.
|
||||
|
||||
The provided arguments determines the scope of the check:
|
||||
- a storage root: the whole storage (all personal and project spaces) is scanned
|
||||
- a space root: only that space is scanned
|
||||
- a file or directory: only that single resource is scanned (and its children, if it is a directory)
|
||||
|
||||
Any specified file or directory must be underneath the storage root directory and if that is not the case,
|
||||
the command is aborted with an error before performing any scanning.`,
|
||||
Args: cobra.ArbitraryArgs,
|
||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
if err := parser.ParseConfig(ocCfg, true); err != nil {
|
||||
return configlog.ReturnError(err)
|
||||
}
|
||||
@@ -93,432 +88,281 @@ func scanCmd(ocCfg *config.Config) *cobra.Command {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// We want to initialize the driver but disable scanfs on boot, so we can trigger it manually afterwards
|
||||
drivers := revaconfig.StorageProviderDrivers(cfg)
|
||||
drivers["posix"] = revaconfig.Posix(cfg, false, false)
|
||||
|
||||
var fsStream events.Stream
|
||||
var err error
|
||||
fsStream, err = event.NewStream(cfg)
|
||||
haltOnError, err := cmd.Flags().GetBool("halt-on-error")
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to create event stream for posix driver: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
f, ok := registry.NewFuncs["posix"]
|
||||
if !ok {
|
||||
fmt.Fprintf(os.Stderr, "posix driver not found in registry\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fs, err := f(drivers["posix"].(map[string]any), fsStream, nil)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to initialize filesystem driver '%s': %v\n", cfg.Driver, err)
|
||||
return err
|
||||
}
|
||||
|
||||
cacher, ok := fs.(IDCacher)
|
||||
if !ok {
|
||||
fmt.Fprintf(os.Stderr, "The posix driver does not expose WarmupIDCache.\n")
|
||||
os.Exit(1)
|
||||
storageRoot := cfg.Drivers.Posix.Root
|
||||
paths := []string{storageRoot}
|
||||
if len(args) > 0 {
|
||||
paths = []string{}
|
||||
for _, v := range args {
|
||||
path := v
|
||||
if !filepath.IsAbs(path) {
|
||||
if v, err := filepath.Abs(path); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to make the specified path %q absolute: %v\n", v, err)
|
||||
os.Exit(1)
|
||||
} else {
|
||||
path = v
|
||||
}
|
||||
}
|
||||
// not ensuring whether the path is under the storage root here, will be done when iterating over them
|
||||
path = filepath.Clean(path)
|
||||
paths = append(paths, path)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("Starting posixfs scan...")
|
||||
err = cacher.WarmupIDCache(cfg.Drivers.Posix.Root, true, false)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Scan failed: %v\n", err)
|
||||
return err
|
||||
var scan func(path string) error = nil
|
||||
{
|
||||
// We want to initialize the driver but disable scanfs on boot, so we can trigger it manually afterwards
|
||||
drivers := revaconfig.StorageProviderDrivers(cfg)
|
||||
drivers["posix"] = revaconfig.Posix(cfg, false, false)
|
||||
|
||||
var fsStream events.Stream
|
||||
var err error
|
||||
fsStream, err = event.NewStream(cfg)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to create event stream for posix driver: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
log := logger("posixfs")
|
||||
|
||||
f, ok := registry.NewFuncs["posix"]
|
||||
if !ok {
|
||||
fmt.Fprintf(os.Stderr, "posix driver not found in registry\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fs, err := f(drivers["posix"].(map[string]any), fsStream, &log)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to initialize filesystem driver '%s': %v\n", cfg.Driver, err)
|
||||
return err
|
||||
}
|
||||
|
||||
cacher, ok := fs.(IDCacher)
|
||||
if !ok {
|
||||
fmt.Fprintf(os.Stderr, "The posix driver does not expose WarmupIDCache.\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
scan = func(path string) error {
|
||||
err := cacher.WarmupIDCache(path, true, false)
|
||||
if err != nil {
|
||||
logFailure("Error scanning path '%s': %v", path, err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("Scan completed successfully.")
|
||||
return nil
|
||||
errors := processPosixFsResources(paths, !haltOnError,
|
||||
func(path string) error {
|
||||
fmt.Println("Scanning personal spaces...")
|
||||
return scan(path)
|
||||
},
|
||||
func(path string) error {
|
||||
fmt.Println("Scanning project spaces...")
|
||||
return scan(path)
|
||||
},
|
||||
func(path string) error {
|
||||
fmt.Printf("Scanning space '%s'...\n", path)
|
||||
return scan(path)
|
||||
},
|
||||
func(path string) error {
|
||||
fmt.Printf("Scanning '%s'...\n", path)
|
||||
return scan(path)
|
||||
},
|
||||
)
|
||||
|
||||
if len(errors) == 0 {
|
||||
fmt.Println("Scan completed successfully.")
|
||||
return nil
|
||||
} else {
|
||||
plural := "s"
|
||||
if len(errors) == 1 {
|
||||
plural = ""
|
||||
}
|
||||
verb := "completed"
|
||||
if haltOnError {
|
||||
verb = "aborted"
|
||||
}
|
||||
return fmt.Errorf("scan %s with %d error%s", verb, len(errors), plural)
|
||||
}
|
||||
},
|
||||
}
|
||||
return cmd
|
||||
scanCmd.Flags().BoolP("halt-on-error", "E", false, "Halt at once when an error occurs when processing one of the paths (default behaviour is to keep going and attempt to process all paths).")
|
||||
return scanCmd
|
||||
}
|
||||
|
||||
// consistencyCmd returns a command to check the consistency of the posixfs storage.
|
||||
func consistencyCmd(cfg *config.Config) *cobra.Command {
|
||||
func consistencyCmd(ocCfg *config.Config) *cobra.Command {
|
||||
consCmd := &cobra.Command{
|
||||
Use: "consistency",
|
||||
Short: "check the consistency of the posixfs storage",
|
||||
Use: "consistency [path ...]",
|
||||
Short: "Check the consistency of the posixfs storage",
|
||||
Long: `Check the consistency of the posixfs storage.
|
||||
|
||||
You can specify one or more paths to limit the scope of the check.
|
||||
If no path is provided, the whole storage is checked.
|
||||
|
||||
The provided arguments determines the scope of the check:
|
||||
- a storage root: the whole storage (all personal and project spaces) is checked
|
||||
- a space root: only that space is checked
|
||||
- a file or directory: only that single entity is checked (and its children, if it is a directory)`,
|
||||
Args: cobra.ArbitraryArgs,
|
||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
|
||||
if err := parser.ParseConfig(ocCfg, true); err != nil {
|
||||
return configlog.ReturnError(err)
|
||||
}
|
||||
|
||||
// Parse storage users config
|
||||
ocCfg.StorageUsers.Commons = ocCfg.Commons
|
||||
|
||||
return configlog.ReturnFatal(storageUsersParser.ParseConfig(ocCfg.StorageUsers))
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return checkPosixfsConsistency(cmd, cfg)
|
||||
cfg := ocCfg.StorageUsers
|
||||
if len(args) == 0 {
|
||||
args = []string{cfg.Drivers.Posix.Root}
|
||||
}
|
||||
log := logger("posixfs")
|
||||
recalculateChecksums, err := cmd.Flags().GetBool("fix-checksums")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
drivers := revaconfig.StorageProviderDrivers(cfg)
|
||||
drivers["posix"] = revaconfig.Posix(cfg, false, false)
|
||||
opts, err := options.New(drivers["posix"].(map[string]any))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ignorer := ignore.NewIgnorer(opts, &log)
|
||||
|
||||
checker := &consistencyChecker{
|
||||
cfg: cfg,
|
||||
ignorer: ignorer,
|
||||
recalculateChecksums: recalculateChecksums,
|
||||
}
|
||||
|
||||
return checker.Check(args)
|
||||
},
|
||||
}
|
||||
consCmd.Flags().StringP("root", "r", "", "Path to the root directory of the posixfs storage")
|
||||
_ = consCmd.MarkFlagRequired("root")
|
||||
|
||||
consCmd.Flags().Bool("fix-checksums", false, "Recalculate and fix the file checksums. This reads every file and can be slow on large storages.")
|
||||
return consCmd
|
||||
}
|
||||
|
||||
// checkPosixfsConsistency checks the consistency of the posixfs storage.
|
||||
func checkPosixfsConsistency(cmd *cobra.Command, cfg *config.Config) error {
|
||||
rootPath, _ := cmd.Flags().GetString("root")
|
||||
indexesPath := filepath.Join(rootPath, "indexes")
|
||||
|
||||
opt, _ := options.New(map[string]interface{}{
|
||||
"root": rootPath,
|
||||
})
|
||||
log := zerolog.Nop()
|
||||
ignorer = ignore.NewIgnorer(opt, &log)
|
||||
|
||||
_, err := os.Stat(indexesPath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return fmt.Errorf("consistency check failed: '%s' is not a posixfs root", rootPath)
|
||||
}
|
||||
return fmt.Errorf("error accessing '%s': %w", indexesPath, err)
|
||||
}
|
||||
|
||||
spinnerCfg := yacspin.Config{
|
||||
Frequency: 100 * time.Millisecond,
|
||||
CharSet: yacspin.CharSets[11],
|
||||
StopCharacter: "✓",
|
||||
StopColors: []string{"fgGreen"},
|
||||
StopFailCharacter: "✗",
|
||||
StopFailColors: []string{"fgRed"},
|
||||
}
|
||||
|
||||
spinner, err = yacspin.New(spinnerCfg)
|
||||
err = spinner.Start()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating spinner: %w", err)
|
||||
}
|
||||
|
||||
checkSpaces(filepath.Join(rootPath, "users"))
|
||||
spinner.Suffix(" Personal spaces check ")
|
||||
spinner.StopMessage("completed\n")
|
||||
spinner.Stop()
|
||||
|
||||
checkSpaces(filepath.Join(rootPath, "projects"))
|
||||
spinner.Suffix(" Project spaces check ")
|
||||
spinner.StopMessage("completed")
|
||||
spinner.Stop()
|
||||
|
||||
if restartRequired {
|
||||
fmt.Println("\n\n ⚠️ Please restart your openCloud instance to apply changes.")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkSpaces(basePath string) {
|
||||
dirEntries, err := os.ReadDir(basePath)
|
||||
if err != nil {
|
||||
spinner.Message(fmt.Sprintf("Error reading spaces directory '%s'\n", basePath))
|
||||
spinner.StopFail()
|
||||
return
|
||||
}
|
||||
|
||||
for _, entry := range dirEntries {
|
||||
if entry.IsDir() {
|
||||
fullPath := filepath.Join(basePath, entry.Name())
|
||||
checkSpace(fullPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func checkSpace(spacePath string) {
|
||||
spinner.Message("")
|
||||
spinner.Suffix(fmt.Sprintf(" Checking space '%s'", spacePath))
|
||||
|
||||
info, err := os.Stat(spacePath)
|
||||
if err != nil {
|
||||
logFailure("Error accessing path '%s': %v", spacePath, err)
|
||||
return
|
||||
}
|
||||
if !info.IsDir() {
|
||||
logFailure("Error: The provided path '%s' is not a directory\n", spacePath)
|
||||
return
|
||||
}
|
||||
|
||||
spaceID, err := xattr.Get(spacePath, spaceIDAttrName)
|
||||
if err != nil || len(spaceID) == 0 {
|
||||
logFailure("Error: The directory '%s' does not seem to be a space root, it's missing the '%s' attribute\n", spacePath, spaceIDAttrName)
|
||||
return
|
||||
}
|
||||
|
||||
checkSpaceID(spacePath)
|
||||
checkNodeIDs(spacePath)
|
||||
}
|
||||
|
||||
func checkSpaceID(spacePath string) {
|
||||
spinner.Message(" - checking space ID uniqueness")
|
||||
|
||||
entries, uniqueIDs, oldestEntry, err := gatherAttributes(spacePath)
|
||||
if err != nil {
|
||||
logFailure("Failed to gather attributes: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(entries) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if len(uniqueIDs) > 1 {
|
||||
spinner.Pause()
|
||||
fmt.Println("\n ⚠ Multiple space IDs found:")
|
||||
for id := range uniqueIDs {
|
||||
fmt.Printf(" - %s\n", id)
|
||||
}
|
||||
|
||||
fmt.Printf("\n ⏳ Oldest entry is '%s' (modified on %s).\n",
|
||||
filepath.Base(oldestEntry.Path), oldestEntry.ModTime.Format(time.RFC1123))
|
||||
|
||||
targetID := oldestEntry.ParentID
|
||||
fmt.Printf(" ✅ Proposed target Parent ID: %s\n", targetID)
|
||||
|
||||
fmt.Printf("\n Do you want to unify all parent IDs to '%s'? This will modify %d entries, the directory, and the user index. (y/N): ", targetID, len(entries))
|
||||
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
input, _ := reader.ReadString('\n')
|
||||
input = strings.TrimSpace(strings.ToLower(input))
|
||||
|
||||
if input != "y" {
|
||||
spinner.Unpause()
|
||||
logFailure("Operation cancelled by user.")
|
||||
return
|
||||
}
|
||||
restartRequired = true
|
||||
|
||||
obsoleteIDs := []string{}
|
||||
for id := range uniqueIDs {
|
||||
if id != targetID {
|
||||
obsoleteIDs = append(obsoleteIDs, id)
|
||||
}
|
||||
}
|
||||
fixSpaceID(spacePath, obsoleteIDs, targetID, entries)
|
||||
spinner.Unpause()
|
||||
}
|
||||
}
|
||||
|
||||
func walkParentIDs(dir string, parentID string) int {
|
||||
fixes := 0
|
||||
entries, err := os.ReadDir(dir)
|
||||
if err != nil {
|
||||
logFailure("Error reading directory '%s': %v", dir, err)
|
||||
return 0
|
||||
}
|
||||
|
||||
for _, entry := range entries {
|
||||
fullPath := filepath.Join(dir, entry.Name())
|
||||
|
||||
if ignorer.IsIgnored(fullPath) {
|
||||
continue
|
||||
}
|
||||
|
||||
actualParentID, err := xattr.Get(fullPath, parentIDAttrName)
|
||||
if err != nil || string(actualParentID) != parentID {
|
||||
err = xattr.Set(fullPath, parentIDAttrName, []byte(parentID))
|
||||
if err != nil {
|
||||
logFailure("Failed to fix parent ID for '%s': %v", fullPath, err)
|
||||
} else {
|
||||
spinner.Pause()
|
||||
fmt.Printf("\n + Fixed parent ID for '%s'\n", fullPath)
|
||||
spinner.Unpause()
|
||||
fixes++
|
||||
restartRequired = true
|
||||
}
|
||||
}
|
||||
|
||||
if entry.IsDir() {
|
||||
nodeID, err := xattr.Get(fullPath, idAttrName)
|
||||
if err != nil || len(nodeID) == 0 {
|
||||
logFailure("Directory '%s' missing '%s', skipping its children", fullPath, idAttrName)
|
||||
continue
|
||||
}
|
||||
walkParentIDs(fullPath, string(nodeID))
|
||||
}
|
||||
}
|
||||
return fixes
|
||||
}
|
||||
|
||||
func checkNodeIDs(spacePath string) {
|
||||
spinner.Message(" - checking parent IDs")
|
||||
|
||||
rootID, err := xattr.Get(spacePath, idAttrName)
|
||||
if err != nil || len(rootID) == 0 {
|
||||
logFailure("Space root '%s' missing '%s' attribute", spacePath, idAttrName)
|
||||
return
|
||||
}
|
||||
|
||||
fixes := walkParentIDs(spacePath, string(rootID))
|
||||
|
||||
if fixes > 0 {
|
||||
spinner.Pause()
|
||||
fmt.Printf("\n ✓ Fixed %d incorrect parent IDs in %s\n", fixes, filepath.Base(spacePath))
|
||||
spinner.Unpause()
|
||||
}
|
||||
}
|
||||
|
||||
func fixSpaceID(spacePath string, obsoleteIDs []string, targetID string, entries []EntryInfo) {
|
||||
// Set all parentid attributes to the proper space ID
|
||||
err := setAllParentIDAttributes(entries, targetID)
|
||||
if err != nil {
|
||||
logFailure("an error occurred during file attribute update: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Update space ID itself
|
||||
fmt.Printf(" Updating directory '%s' with attribute '%s' -> %s\n", filepath.Base(spacePath), idAttrName, targetID)
|
||||
err = xattr.Set(spacePath, idAttrName, []byte(targetID))
|
||||
if err != nil {
|
||||
logFailure("Failed to set attribute on directory '%s': %v", spacePath, err)
|
||||
return
|
||||
}
|
||||
err = xattr.Set(spacePath, spaceIDAttrName, []byte(targetID))
|
||||
if err != nil {
|
||||
logFailure("Failed to set attribute on directory '%s': %v", spacePath, err)
|
||||
return
|
||||
}
|
||||
|
||||
// update the index
|
||||
err = updateOwnerIndexFile(spacePath, obsoleteIDs)
|
||||
if err != nil {
|
||||
logFailure("Could not update the owner index file: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func gatherAttributes(path string) ([]EntryInfo, map[string]struct{}, EntryInfo, error) {
|
||||
dirEntries, err := os.ReadDir(path)
|
||||
if err != nil {
|
||||
return nil, nil, EntryInfo{}, fmt.Errorf("failed to read directory: %w", err)
|
||||
}
|
||||
|
||||
var allEntries []EntryInfo
|
||||
uniqueIDs := make(map[string]struct{})
|
||||
var oldestEntry EntryInfo
|
||||
oldestTime := time.Now().Add(100 * 365 * 24 * time.Hour) // Set to a future date to find the oldest entry
|
||||
|
||||
for _, entry := range dirEntries {
|
||||
fullPath := filepath.Join(path, entry.Name())
|
||||
if ignorer.IsIgnored(fullPath) {
|
||||
continue
|
||||
}
|
||||
info, err := os.Stat(fullPath)
|
||||
if err != nil {
|
||||
fmt.Printf(" - Warning: could not stat %s: %v\n", entry.Name(), err)
|
||||
continue
|
||||
}
|
||||
|
||||
parentID, err := xattr.Get(fullPath, parentIDAttrName)
|
||||
if err != nil {
|
||||
continue // Skip if attribute doesn't exist or can't be read
|
||||
}
|
||||
|
||||
entryInfo := EntryInfo{
|
||||
Path: fullPath,
|
||||
ModTime: info.ModTime(),
|
||||
ParentID: string(parentID),
|
||||
}
|
||||
|
||||
allEntries = append(allEntries, entryInfo)
|
||||
uniqueIDs[string(parentID)] = struct{}{}
|
||||
|
||||
if entryInfo.ModTime.Before(oldestTime) {
|
||||
oldestTime = entryInfo.ModTime
|
||||
oldestEntry = entryInfo
|
||||
}
|
||||
}
|
||||
|
||||
return allEntries, uniqueIDs, oldestEntry, nil
|
||||
}
|
||||
|
||||
func setAllParentIDAttributes(entries []EntryInfo, targetID string) error {
|
||||
fmt.Printf(" Setting all parent IDs to '%s':\n", targetID)
|
||||
|
||||
for _, entry := range entries {
|
||||
if entry.ParentID == targetID {
|
||||
fmt.Printf(" - Skipping '%s' (already has target ID).\n", filepath.Base(entry.Path))
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Printf(" - Removing all attributes from '%s'. It will be re-assimilated\n", filepath.Base(entry.Path))
|
||||
filepath.WalkDir(entry.Path, func(path string, d os.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("error walking path '%s': %w", path, err)
|
||||
}
|
||||
|
||||
// Remove all attributes from the file.
|
||||
if err := removeAttributes(path); err != nil {
|
||||
fmt.Printf("failed to remove attributes from '%s': %v", path, err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// updateOwnerIndexFile handles the logic of reading, modifying, and writing the MessagePack index file.
|
||||
func updateOwnerIndexFile(basePath string, obsoleteIDs []string) error {
|
||||
fmt.Printf(" Rewriting index file '%s'\n", basePath)
|
||||
|
||||
ownerID, err := xattr.Get(basePath, ownerIDAttrName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not get owner ID from oldest entry '%s' to find index: %w", basePath, err)
|
||||
}
|
||||
|
||||
indexPath := filepath.Join(basePath, "../../indexes/by-user-id", string(ownerID)+".mpk")
|
||||
indexPath = filepath.Clean(indexPath)
|
||||
|
||||
// Read the MessagePack file
|
||||
fileData, err := os.ReadFile(indexPath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return fmt.Errorf("index file does not exist, skipping update")
|
||||
}
|
||||
return fmt.Errorf("could not read index file: %w", err)
|
||||
}
|
||||
var indexMap map[string]string
|
||||
if err := msgpack.Unmarshal(fileData, &indexMap); err != nil {
|
||||
return fmt.Errorf("failed to parse MessagePack index file (is it corrupt?): %w", err)
|
||||
}
|
||||
|
||||
// Remove obsolete IDs from the map
|
||||
itemsRemoved := 0
|
||||
for _, id := range obsoleteIDs {
|
||||
if _, exists := indexMap[id]; exists {
|
||||
fmt.Printf(" - Removing obsolete ID '%s' from index.\n", id)
|
||||
delete(indexMap, id)
|
||||
itemsRemoved++
|
||||
} else {
|
||||
fmt.Printf(" - Obsolete ID '%s' not found in index\n", id)
|
||||
}
|
||||
}
|
||||
|
||||
if itemsRemoved == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Write the data back to the file
|
||||
updatedData, err := msgpack.Marshal(&indexMap)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal updated index map: %w", err)
|
||||
}
|
||||
if err := os.WriteFile(indexPath, updatedData, 0644); err != nil {
|
||||
return fmt.Errorf("failed to write updated index file: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf(" ✓ Successfully removed %d item(s) and saved index file.\n", itemsRemoved)
|
||||
return nil
|
||||
}
|
||||
|
||||
func removeAttributes(path string) error {
|
||||
attrNames, err := xattr.List(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to list attributes for '%s': %w", path, err)
|
||||
}
|
||||
|
||||
for _, attrName := range attrNames {
|
||||
if err := xattr.Remove(path, attrName); err != nil {
|
||||
return fmt.Errorf("failed to remove attribute '%s' from '%s': %w", attrName, path, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func logFailure(message string, args ...any) {
|
||||
spinner.StopFailMessage(fmt.Sprintf("\n"+message, args...))
|
||||
spinner.StopFail()
|
||||
spinner.Start()
|
||||
fmt.Fprintf(os.Stderr, message+"\n", args...)
|
||||
}
|
||||
|
||||
// findStorageRoot walks up the directory tree starting at path until it finds a
|
||||
// directory that contains an "indexes" subdirectory which marks the root of a
|
||||
// posixfs storage. A user directory inside a space might also be named "indexes",
|
||||
// so to disambiguate we require that the "indexes" directory is an internal
|
||||
// directory: the storage's own indexes directory is skipped during assimilation
|
||||
// and therefore never receives a node ID attribute, whereas a regular user
|
||||
// directory would have one.
|
||||
func findStorageRoot(path string) (string, error) {
|
||||
current := path
|
||||
for {
|
||||
indexesPath := filepath.Join(current, "indexes")
|
||||
if info, err := os.Stat(indexesPath); err == nil && info.IsDir() {
|
||||
if id, err := xattr.Get(indexesPath, prefixes.IDAttr); err != nil || len(id) == 0 {
|
||||
return current, nil
|
||||
}
|
||||
}
|
||||
|
||||
parent := filepath.Dir(current)
|
||||
if parent == current {
|
||||
return "", fmt.Errorf("'%s' does not appear to be inside a posixfs storage (no 'indexes' directory found)", path)
|
||||
}
|
||||
current = parent
|
||||
}
|
||||
}
|
||||
|
||||
// isSpaceRoot reports whether the given path is a space root, which is
|
||||
// identified by the presence of the space ID attribute.
|
||||
func isSpaceRoot(path string) bool {
|
||||
spaceID, err := xattr.Get(path, prefixes.SpaceIDAttr)
|
||||
return err == nil && len(spaceID) > 0
|
||||
}
|
||||
|
||||
// iterates over a list of paths and processes them all, using the appropriate function
|
||||
// depending on the type of resource
|
||||
//
|
||||
// note that whenever an error occurs, it collects that error and continues processing
|
||||
// subsequent paths, and then returns a slice of errors at the end (or an empty slice
|
||||
// if no errors occured)
|
||||
func processPosixFsResources(paths []string,
|
||||
keepGoing bool,
|
||||
personalSpaceDir func(string) error,
|
||||
projectSpaceDir func(string) error,
|
||||
spaceRoot func(string) error,
|
||||
entity func(string) error,
|
||||
) []error {
|
||||
// no need to guard this with a mutex for now, since the implementation is not parallelized
|
||||
errors := []error{}
|
||||
|
||||
for _, path := range paths {
|
||||
rootPath, err := findStorageRoot(path)
|
||||
if err != nil {
|
||||
errors = append(errors, err)
|
||||
logFailure("error: %s", err)
|
||||
if keepGoing {
|
||||
continue
|
||||
} else {
|
||||
return errors
|
||||
}
|
||||
}
|
||||
path = filepath.Clean(path)
|
||||
if _, err := os.Stat(path); err != nil {
|
||||
errors = append(errors, err)
|
||||
logFailure("error accessing '%s': %w", path, err)
|
||||
if keepGoing {
|
||||
continue
|
||||
} else {
|
||||
return errors
|
||||
}
|
||||
}
|
||||
contained, _ := filepathx.IsSameOrContainedBy(rootPath, path)
|
||||
|
||||
switch {
|
||||
case path == rootPath:
|
||||
if err := personalSpaceDir(filepath.Join(path, "users")); err != nil {
|
||||
errors = append(errors, err)
|
||||
if !keepGoing {
|
||||
return errors
|
||||
}
|
||||
}
|
||||
if err := projectSpaceDir(filepath.Join(path, "projects")); err != nil {
|
||||
errors = append(errors, err)
|
||||
if !keepGoing {
|
||||
return errors
|
||||
}
|
||||
}
|
||||
case isSpaceRoot(path):
|
||||
if err := spaceRoot(path); err != nil {
|
||||
errors = append(errors, err)
|
||||
if !keepGoing {
|
||||
return errors
|
||||
}
|
||||
}
|
||||
case contained:
|
||||
if err := entity(path); err != nil {
|
||||
errors = append(errors, err)
|
||||
if !keepGoing {
|
||||
return errors
|
||||
}
|
||||
}
|
||||
default:
|
||||
err := fmt.Errorf("error: the provided path '%s' is neither a space root nor contained by the storage root '%s'", path, rootPath)
|
||||
errors = append(errors, err)
|
||||
logFailure(err.Error())
|
||||
if !keepGoing {
|
||||
return errors
|
||||
}
|
||||
}
|
||||
}
|
||||
return errors
|
||||
}
|
||||
@@ -0,0 +1,489 @@
|
||||
// Copyright 2026 OpenCloud GmbH <mail@opencloud.eu>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package command
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
storageUsersConfig "github.com/opencloud-eu/opencloud/services/storage-users/pkg/config"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/storage/fs/posix/ignore"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/storage/pkg/decomposedfs/metadata/prefixes"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/storage/pkg/decomposedfs/node"
|
||||
"github.com/pkg/xattr"
|
||||
"github.com/shamaton/msgpack/v2"
|
||||
)
|
||||
|
||||
type consistencyChecker struct {
|
||||
cfg *storageUsersConfig.Config
|
||||
ignorer *ignore.Ignorer
|
||||
recalculateChecksums bool
|
||||
|
||||
restartRequired bool
|
||||
}
|
||||
|
||||
// checkPosixfsConsistency checks the consistency of the posixfs storage. The
|
||||
// given path determines the scope of the check: the whole storage, a single
|
||||
// space or a single entity within a space.
|
||||
func (c *consistencyChecker) Check(paths []string) error {
|
||||
_ = processPosixFsResources(paths, true,
|
||||
func(path string) error {
|
||||
fmt.Println("Checking personal spaces...")
|
||||
c.checkSpaces(path)
|
||||
return nil
|
||||
},
|
||||
func(path string) error {
|
||||
fmt.Println("Checking project spaces...")
|
||||
c.checkSpaces(path)
|
||||
return nil
|
||||
},
|
||||
func(path string) error {
|
||||
fmt.Printf("Checking space '%s'...\n", path)
|
||||
c.checkSpace(path)
|
||||
return nil
|
||||
},
|
||||
func(path string) error {
|
||||
if c.ignorer.IsIgnored(path) {
|
||||
return nil
|
||||
}
|
||||
fmt.Printf("Checking '%s'...\n", path)
|
||||
c.checkEntity(path)
|
||||
return nil
|
||||
},
|
||||
)
|
||||
if c.restartRequired {
|
||||
fmt.Println("\n\n ⚠️ Please restart your openCloud instance to apply changes.")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *consistencyChecker) checkSpaces(basePath string) {
|
||||
dirEntries, err := os.ReadDir(basePath)
|
||||
if err != nil {
|
||||
logFailure("Error reading spaces directory '%s': %v", basePath, err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, entry := range dirEntries {
|
||||
if entry.IsDir() {
|
||||
fullPath := filepath.Join(basePath, entry.Name())
|
||||
c.checkSpace(fullPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *consistencyChecker) checkSpace(spacePath string) {
|
||||
info, err := os.Stat(spacePath)
|
||||
if err != nil {
|
||||
logFailure("Error accessing path '%s': %v", spacePath, err)
|
||||
return
|
||||
}
|
||||
if !info.IsDir() {
|
||||
logFailure("Error: The provided path '%s' is not a directory\n", spacePath)
|
||||
return
|
||||
}
|
||||
|
||||
spaceID, err := xattr.Get(spacePath, prefixes.SpaceIDAttr)
|
||||
if err != nil || len(spaceID) == 0 {
|
||||
logFailure("Error: The directory '%s' does not seem to be a space root, it's missing the '%s' attribute\n", spacePath, prefixes.SpaceIDAttr)
|
||||
return
|
||||
}
|
||||
|
||||
c.checkSpaceID(spacePath)
|
||||
c.checkNodes(spacePath)
|
||||
}
|
||||
|
||||
func (c *consistencyChecker) checkSpaceID(spacePath string) {
|
||||
entries, uniqueIDs, oldestEntry, err := c.gatherAttributes(spacePath)
|
||||
if err != nil {
|
||||
logFailure("Failed to gather attributes: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(entries) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if len(uniqueIDs) > 1 {
|
||||
fmt.Println("\n ⚠ Multiple space IDs found:")
|
||||
for id := range uniqueIDs {
|
||||
fmt.Printf(" - %s\n", id)
|
||||
}
|
||||
|
||||
fmt.Printf("\n ⏳ Oldest entry is '%s' (modified on %s).\n",
|
||||
filepath.Base(oldestEntry.Path), oldestEntry.ModTime.Format(time.RFC1123))
|
||||
|
||||
targetID := oldestEntry.ParentID
|
||||
fmt.Printf(" ✅ Proposed target Parent ID: %s\n", targetID)
|
||||
|
||||
fmt.Printf("\n Do you want to unify all parent IDs to '%s'? This will modify %d entries, the directory, and the user index. (y/N): ", targetID, len(entries))
|
||||
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
input, _ := reader.ReadString('\n')
|
||||
input = strings.TrimSpace(strings.ToLower(input))
|
||||
|
||||
if input != "y" {
|
||||
logFailure("Operation cancelled by user.")
|
||||
return
|
||||
}
|
||||
c.restartRequired = true
|
||||
|
||||
obsoleteIDs := []string{}
|
||||
for id := range uniqueIDs {
|
||||
if id != targetID {
|
||||
obsoleteIDs = append(obsoleteIDs, id)
|
||||
}
|
||||
}
|
||||
c.fixSpaceID(spacePath, obsoleteIDs, targetID, entries)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *consistencyChecker) walkNodes(dir string, parentID string) int {
|
||||
fixes := 0
|
||||
entries, err := os.ReadDir(dir)
|
||||
if err != nil {
|
||||
logFailure("Error reading directory '%s': %v", dir, err)
|
||||
return 0
|
||||
}
|
||||
|
||||
for _, entry := range entries {
|
||||
fullPath := filepath.Join(dir, entry.Name())
|
||||
|
||||
if c.ignorer.IsIgnored(fullPath) {
|
||||
continue
|
||||
}
|
||||
|
||||
fixes += c.checkNodeAttributes(fullPath, entry.Name(), parentID, entry.IsDir())
|
||||
|
||||
if entry.IsDir() {
|
||||
nodeID, err := xattr.Get(fullPath, prefixes.IDAttr)
|
||||
if err != nil || len(nodeID) == 0 {
|
||||
logFailure("Directory '%s' missing '%s', skipping its children", fullPath, prefixes.IDAttr)
|
||||
continue
|
||||
}
|
||||
fixes += c.walkNodes(fullPath, string(nodeID))
|
||||
}
|
||||
}
|
||||
return fixes
|
||||
}
|
||||
|
||||
// checkNodeAttributes checks and fixes the parent ID and name attributes of a
|
||||
// single node. For files it additionally checks the blobsize and, when
|
||||
// requested, the checksums. It returns the number of fixes applied.
|
||||
func (c *consistencyChecker) checkNodeAttributes(path, name, parentID string, isDir bool) int {
|
||||
fixes := 0
|
||||
|
||||
// Check if the parent ID attribute matches the expected parent ID, if not, fix it.
|
||||
actualParentID, err := xattr.Get(path, prefixes.ParentidAttr)
|
||||
if err != nil || string(actualParentID) != parentID {
|
||||
if err := xattr.Set(path, prefixes.ParentidAttr, []byte(parentID)); err != nil {
|
||||
logFailure("Failed to fix parent ID for '%s': %v", path, err)
|
||||
} else {
|
||||
fmt.Printf(" + Fixed parent ID for '%s'\n", path)
|
||||
fixes++
|
||||
c.restartRequired = true
|
||||
}
|
||||
}
|
||||
|
||||
// Check that the name attribute matches the actual name of the file/directory, if not, fix it.
|
||||
nameAttr, err := xattr.Get(path, prefixes.NameAttr)
|
||||
if err != nil || string(nameAttr) != name {
|
||||
if err := xattr.Set(path, prefixes.NameAttr, []byte(name)); err != nil {
|
||||
logFailure("Failed to fix name attribute for '%s': %v", path, err)
|
||||
} else {
|
||||
fmt.Printf(" + Fixed name attribute for '%s'\n", path)
|
||||
fixes++
|
||||
c.restartRequired = true
|
||||
}
|
||||
}
|
||||
|
||||
if !isDir {
|
||||
fixes += c.checkBlobsize(path)
|
||||
if c.recalculateChecksums {
|
||||
fixes += c.fixChecksums(path)
|
||||
}
|
||||
}
|
||||
|
||||
return fixes
|
||||
}
|
||||
|
||||
// checkEntity checks a single file or directory within a space, including its own
|
||||
// parent ID, name and (for files) blobsize/checksums. If the entity is a directory
|
||||
// its children are checked recursively.
|
||||
func (c *consistencyChecker) checkEntity(path string) {
|
||||
info, err := os.Stat(path)
|
||||
if err != nil {
|
||||
logFailure("Error accessing path '%s': %v", path, err)
|
||||
return
|
||||
}
|
||||
|
||||
// The expected parent ID is the ID attribute of the containing directory.
|
||||
parentDir := filepath.Dir(path)
|
||||
parentID, err := xattr.Get(parentDir, prefixes.IDAttr)
|
||||
if err != nil || len(parentID) == 0 {
|
||||
logFailure("Parent directory '%s' is missing the '%s' attribute", parentDir, prefixes.IDAttr)
|
||||
return
|
||||
}
|
||||
|
||||
fixes := c.checkNodeAttributes(path, info.Name(), string(parentID), info.IsDir())
|
||||
|
||||
if info.IsDir() {
|
||||
nodeID, err := xattr.Get(path, prefixes.IDAttr)
|
||||
if err != nil || len(nodeID) == 0 {
|
||||
logFailure("Directory '%s' missing '%s' attribute", path, prefixes.IDAttr)
|
||||
} else {
|
||||
fixes += c.walkNodes(path, string(nodeID))
|
||||
}
|
||||
}
|
||||
|
||||
if fixes > 0 {
|
||||
fmt.Printf(" ✓ Fixed %d incorrect node attributes for %s\n", fixes, filepath.Base(path))
|
||||
}
|
||||
}
|
||||
|
||||
// checkBlobsize verifies that the stored blobsize attribute matches the actual
|
||||
// file size and fixes it if it doesn't. It returns the number of fixes applied.
|
||||
func (c *consistencyChecker) checkBlobsize(path string) int {
|
||||
info, err := os.Stat(path)
|
||||
if err != nil {
|
||||
logFailure("Error accessing file '%s': %v", path, err)
|
||||
return 0
|
||||
}
|
||||
|
||||
expectedSize := strconv.FormatInt(info.Size(), 10)
|
||||
blobsize, err := xattr.Get(path, prefixes.BlobsizeAttr)
|
||||
if err == nil && string(blobsize) == expectedSize {
|
||||
return 0
|
||||
}
|
||||
|
||||
if err := xattr.Set(path, prefixes.BlobsizeAttr, []byte(expectedSize)); err != nil {
|
||||
logFailure("Failed to fix blobsize for '%s': %v", path, err)
|
||||
return 0
|
||||
}
|
||||
|
||||
fmt.Printf(" + Fixed blobsize for '%s'\n", path)
|
||||
c.restartRequired = true
|
||||
return 1
|
||||
}
|
||||
|
||||
// fixChecksums recalculates the sha1, md5 and adler32 checksums of the file and
|
||||
// updates the stored attributes if they differ. It returns the number of fixes applied.
|
||||
func (c *consistencyChecker) fixChecksums(path string) int {
|
||||
sha1h, md5h, adler32h, err := node.CalculateChecksums(context.Background(), path)
|
||||
if err != nil {
|
||||
logFailure("Failed to calculate checksums for '%s': %v", path, err)
|
||||
return 0
|
||||
}
|
||||
|
||||
checksums := map[string][]byte{
|
||||
prefixes.ChecksumPrefix + "sha1": sha1h.Sum(nil),
|
||||
prefixes.ChecksumPrefix + "md5": md5h.Sum(nil),
|
||||
prefixes.ChecksumPrefix + "adler32": adler32h.Sum(nil),
|
||||
}
|
||||
|
||||
fixes := 0
|
||||
for attrName, sum := range checksums {
|
||||
current, err := xattr.Get(path, attrName)
|
||||
if err == nil && bytes.Equal(current, sum) {
|
||||
continue
|
||||
}
|
||||
if err := xattr.Set(path, attrName, sum); err != nil {
|
||||
logFailure("Failed to fix checksum '%s' for '%s': %v", attrName, path, err)
|
||||
continue
|
||||
}
|
||||
fmt.Printf(" + Fixed checksum '%s' for '%s'\n", attrName, path)
|
||||
c.restartRequired = true
|
||||
fixes++
|
||||
}
|
||||
return fixes
|
||||
}
|
||||
|
||||
func (c *consistencyChecker) checkNodes(spacePath string) {
|
||||
rootID, err := xattr.Get(spacePath, prefixes.IDAttr)
|
||||
if err != nil || len(rootID) == 0 {
|
||||
logFailure("Space root '%s' missing '%s' attribute", spacePath, prefixes.IDAttr)
|
||||
return
|
||||
}
|
||||
|
||||
fixes := c.walkNodes(spacePath, string(rootID))
|
||||
|
||||
if fixes > 0 {
|
||||
fmt.Printf(" ✓ Fixed %d incorrect node attributes in %s\n", fixes, filepath.Base(spacePath))
|
||||
}
|
||||
}
|
||||
|
||||
// fixSpaceID updates the parentid attributes of all entries in a space to a new target ID,
|
||||
// updates the space's own ID attributes, and removes obsolete IDs from the user index file.
|
||||
func (c *consistencyChecker) fixSpaceID(spacePath string, obsoleteIDs []string, targetID string, entries []EntryInfo) {
|
||||
// Set all parentid attributes to the proper space ID
|
||||
err := setAllParentIDAttributes(entries, targetID)
|
||||
if err != nil {
|
||||
logFailure("an error occurred during file attribute update: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Update space ID itself
|
||||
fmt.Printf(" Updating directory '%s' with attribute '%s' -> %s\n", filepath.Base(spacePath), prefixes.IDAttr, targetID)
|
||||
err = xattr.Set(spacePath, prefixes.IDAttr, []byte(targetID))
|
||||
if err != nil {
|
||||
logFailure("Failed to set attribute on directory '%s': %v", spacePath, err)
|
||||
return
|
||||
}
|
||||
err = xattr.Set(spacePath, prefixes.SpaceIDAttr, []byte(targetID))
|
||||
if err != nil {
|
||||
logFailure("Failed to set attribute on directory '%s': %v", spacePath, err)
|
||||
return
|
||||
}
|
||||
|
||||
// update the index
|
||||
err = c.updateOwnerIndexFile(spacePath, obsoleteIDs)
|
||||
if err != nil {
|
||||
logFailure("Could not update the owner index file: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *consistencyChecker) gatherAttributes(path string) ([]EntryInfo, map[string]struct{}, EntryInfo, error) {
|
||||
dirEntries, err := os.ReadDir(path)
|
||||
if err != nil {
|
||||
return nil, nil, EntryInfo{}, fmt.Errorf("failed to read directory: %w", err)
|
||||
}
|
||||
|
||||
var allEntries []EntryInfo
|
||||
uniqueIDs := make(map[string]struct{})
|
||||
var oldestEntry EntryInfo
|
||||
oldestTime := time.Now().Add(100 * 365 * 24 * time.Hour) // Set to a future date to find the oldest entry
|
||||
|
||||
for _, entry := range dirEntries {
|
||||
fullPath := filepath.Join(path, entry.Name())
|
||||
if c.ignorer.IsIgnored(fullPath) {
|
||||
continue
|
||||
}
|
||||
info, err := os.Stat(fullPath)
|
||||
if err != nil {
|
||||
fmt.Printf(" - Warning: could not stat %s: %v\n", entry.Name(), err)
|
||||
continue
|
||||
}
|
||||
|
||||
parentID, err := xattr.Get(fullPath, prefixes.ParentidAttr)
|
||||
if err != nil {
|
||||
continue // Skip if attribute doesn't exist or can't be read
|
||||
}
|
||||
|
||||
entryInfo := EntryInfo{
|
||||
Path: fullPath,
|
||||
ModTime: info.ModTime(),
|
||||
ParentID: string(parentID),
|
||||
}
|
||||
|
||||
allEntries = append(allEntries, entryInfo)
|
||||
uniqueIDs[string(parentID)] = struct{}{}
|
||||
|
||||
if entryInfo.ModTime.Before(oldestTime) {
|
||||
oldestTime = entryInfo.ModTime
|
||||
oldestEntry = entryInfo
|
||||
}
|
||||
}
|
||||
|
||||
return allEntries, uniqueIDs, oldestEntry, nil
|
||||
}
|
||||
|
||||
func setAllParentIDAttributes(entries []EntryInfo, targetID string) error {
|
||||
fmt.Printf(" Setting all parent IDs to '%s':\n", targetID)
|
||||
|
||||
for _, entry := range entries {
|
||||
if entry.ParentID == targetID {
|
||||
fmt.Printf(" - Skipping '%s' (already has target ID).\n", filepath.Base(entry.Path))
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Printf(" - Removing all attributes from '%s'. It will be re-assimilated\n", filepath.Base(entry.Path))
|
||||
filepath.WalkDir(entry.Path, func(path string, d os.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("error walking path '%s': %w", path, err)
|
||||
}
|
||||
|
||||
// Remove all attributes from the file.
|
||||
if err := removeAttributes(path); err != nil {
|
||||
fmt.Printf("failed to remove attributes from '%s': %v", path, err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// updateOwnerIndexFile handles the logic of reading, modifying, and writing the MessagePack index file.
|
||||
func (c *consistencyChecker) updateOwnerIndexFile(basePath string, obsoleteIDs []string) error {
|
||||
fmt.Printf(" Rewriting index file '%s'\n", basePath)
|
||||
|
||||
ownerID, err := xattr.Get(basePath, prefixes.OwnerIDAttr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not get owner ID from oldest entry '%s' to find index: %w", basePath, err)
|
||||
}
|
||||
|
||||
indexPath := filepath.Join(c.cfg.Drivers.Posix.Root, "indexes", "by-user-id", string(ownerID)+".mpk")
|
||||
indexPath = filepath.Clean(indexPath)
|
||||
|
||||
// Read the MessagePack file
|
||||
fileData, err := os.ReadFile(indexPath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return fmt.Errorf("index file does not exist, skipping update")
|
||||
}
|
||||
return fmt.Errorf("could not read index file: %w", err)
|
||||
}
|
||||
var indexMap map[string]string
|
||||
if err := msgpack.Unmarshal(fileData, &indexMap); err != nil {
|
||||
return fmt.Errorf("failed to parse MessagePack index file (is it corrupt?): %w", err)
|
||||
}
|
||||
|
||||
// Remove obsolete IDs from the map
|
||||
itemsRemoved := 0
|
||||
for _, id := range obsoleteIDs {
|
||||
if _, exists := indexMap[id]; exists {
|
||||
fmt.Printf(" - Removing obsolete ID '%s' from index.\n", id)
|
||||
delete(indexMap, id)
|
||||
itemsRemoved++
|
||||
} else {
|
||||
fmt.Printf(" - Obsolete ID '%s' not found in index\n", id)
|
||||
}
|
||||
}
|
||||
|
||||
if itemsRemoved == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Write the data back to the file
|
||||
updatedData, err := msgpack.Marshal(&indexMap)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal updated index map: %w", err)
|
||||
}
|
||||
if err := os.WriteFile(indexPath, updatedData, 0644); err != nil {
|
||||
return fmt.Errorf("failed to write updated index file: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf(" ✓ Successfully removed %d item(s) and saved index file.\n", itemsRemoved)
|
||||
return nil
|
||||
}
|
||||
|
||||
func removeAttributes(path string) error {
|
||||
attrNames, err := xattr.List(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to list attributes for '%s': %w", path, err)
|
||||
}
|
||||
|
||||
for _, attrName := range attrNames {
|
||||
if err := xattr.Remove(path, attrName); err != nil {
|
||||
return fmt.Errorf("failed to remove attribute '%s' from '%s': %w", attrName, path, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -25,6 +25,8 @@ var (
|
||||
_nodesGlobPattern = "spaces/*/*/nodes/"
|
||||
)
|
||||
|
||||
const posixDriver = "posix"
|
||||
|
||||
// RevisionsCommand is the entrypoint for the revisions command.
|
||||
func RevisionsCommand(cfg *config.Config) *cobra.Command {
|
||||
revCmd := &cobra.Command{
|
||||
@@ -86,23 +88,28 @@ func PurgeRevisionsCommand(cfg *config.Config) *cobra.Command {
|
||||
mechanism = "glob"
|
||||
}
|
||||
|
||||
var posix = cfg.StorageUsers.Driver == posixDriver
|
||||
|
||||
var ch <-chan string
|
||||
switch mechanism {
|
||||
default:
|
||||
fallthrough
|
||||
case "glob":
|
||||
p := generatePath(basePath, rid)
|
||||
p := generatePath(basePath, rid, posix)
|
||||
if rid.GetOpaqueId() == "" {
|
||||
p = filepath.Join(p, "*/*/*/*/*")
|
||||
}
|
||||
ch = revisions.Glob(p)
|
||||
case "workers":
|
||||
p := generatePath(basePath, rid)
|
||||
p := generatePath(basePath, rid, posix)
|
||||
ch = revisions.GlobWorkers(p, "/*", "/*/*/*/*")
|
||||
case "list":
|
||||
p := filepath.Join(basePath, "spaces")
|
||||
p := basePath
|
||||
if !posix {
|
||||
p = filepath.Join(basePath, "spaces")
|
||||
}
|
||||
if rid != nil {
|
||||
p = generatePath(basePath, rid)
|
||||
p = generatePath(basePath, rid, posix)
|
||||
}
|
||||
ch = revisions.List(p, 10)
|
||||
}
|
||||
@@ -144,22 +151,44 @@ func printResults(countFiles, countBlobs, countRevisions int, dryRun bool) {
|
||||
}
|
||||
}
|
||||
|
||||
func generatePath(basePath string, rid *provider.ResourceId) string {
|
||||
if rid == nil {
|
||||
return filepath.Join(basePath, _nodesGlobPattern)
|
||||
}
|
||||
func generatePath(basePath string, rid *provider.ResourceId, posix bool) string {
|
||||
// decomposedfs and posix store the revisions of a node at different
|
||||
// locations on disk, so the path has to be built per driver:
|
||||
// - decomposedfs: <basePath>/spaces/<pathified spaceID>/nodes/<pathified nodeID>.REV.<ts>
|
||||
// - posix: <basePath>/<users|projects>/<spaceID>/.oc-nodes/<pathified nodeID>.REV.<ts>
|
||||
if posix {
|
||||
if rid == nil {
|
||||
return filepath.Join(basePath, "*", "*", ".oc-nodes")
|
||||
}
|
||||
|
||||
sid := lookup.Pathify(rid.GetSpaceId(), 1, 2)
|
||||
if sid == "" {
|
||||
return ""
|
||||
}
|
||||
nid := lookup.Pathify(rid.GetOpaqueId(), 4, 2)
|
||||
if nid != "" {
|
||||
return filepath.Join(basePath, "*", "*", ".oc-nodes", nid+"*")
|
||||
}
|
||||
|
||||
nid := lookup.Pathify(rid.GetOpaqueId(), 4, 2)
|
||||
if nid == "" {
|
||||
return filepath.Join(basePath, "spaces", sid, "nodes")
|
||||
}
|
||||
if rid.GetSpaceId() == "" {
|
||||
return ""
|
||||
}
|
||||
return filepath.Join(basePath, "*", rid.GetSpaceId(), ".oc-nodes")
|
||||
} else {
|
||||
// decomposedfs
|
||||
if rid == nil {
|
||||
|
||||
return filepath.Join(basePath, "spaces", sid, "nodes", nid+"*")
|
||||
return filepath.Join(basePath, _nodesGlobPattern)
|
||||
}
|
||||
|
||||
sid := lookup.Pathify(rid.GetSpaceId(), 1, 2)
|
||||
if sid == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
nid := lookup.Pathify(rid.GetOpaqueId(), 4, 2)
|
||||
if nid == "" {
|
||||
return filepath.Join(basePath, "spaces", sid, "nodes")
|
||||
}
|
||||
|
||||
return filepath.Join(basePath, "spaces", sid, "nodes", nid+"*")
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
||||
@@ -6,11 +6,13 @@ import (
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/opencloud-eu/opencloud/opencloud/pkg/register"
|
||||
"github.com/opencloud-eu/opencloud/pkg/clihelper"
|
||||
"github.com/opencloud-eu/opencloud/pkg/config"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
oclog "github.com/opencloud-eu/opencloud/pkg/log"
|
||||
)
|
||||
|
||||
// Execute is the entry point for the opencloud command.
|
||||
@@ -38,3 +40,11 @@ func Execute() error {
|
||||
ctx, _ := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
|
||||
return app.ExecuteContext(ctx)
|
||||
}
|
||||
|
||||
func logger(name string) zerolog.Logger {
|
||||
return oclog.NewLogger(
|
||||
oclog.Name(name),
|
||||
oclog.Level("info"),
|
||||
oclog.Pretty(true),
|
||||
oclog.Color(true)).Logger
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
|
||||
@@ -9,7 +11,6 @@ import (
|
||||
"github.com/opencloud-eu/opencloud/pkg/config"
|
||||
"github.com/opencloud-eu/opencloud/pkg/config/configlog"
|
||||
"github.com/opencloud-eu/opencloud/pkg/config/parser"
|
||||
oclog "github.com/opencloud-eu/opencloud/pkg/log"
|
||||
mregistry "github.com/opencloud-eu/opencloud/pkg/registry"
|
||||
sharing "github.com/opencloud-eu/opencloud/services/sharing/pkg/config"
|
||||
sharingparser "github.com/opencloud-eu/opencloud/services/sharing/pkg/config/parser"
|
||||
@@ -22,6 +23,14 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// need to be discussed, for now I will let it here
|
||||
//
|
||||
// Problem:
|
||||
// in reva on CleanupStaleShares call there is migrations invokation, which at leat in tests takes some time,
|
||||
// reva code was modified to wait until migrations are done, to prevent cases when migrations are stuck and the
|
||||
// this executions is not returned this timeout is needed
|
||||
const cleanupTimeout = 1 * time.Minute
|
||||
|
||||
// SharesCommand is the entrypoint for the groups command.
|
||||
func SharesCommand(cfg *config.Config) *cobra.Command {
|
||||
sharesCmd := &cobra.Command{
|
||||
@@ -85,7 +94,7 @@ func cleanup(_ *cobra.Command, cfg *config.Config) error {
|
||||
return configlog.ReturnError(errors.New("cleanup is only implemented for the jsoncs3 share manager"))
|
||||
}
|
||||
|
||||
l := logger()
|
||||
l := logger("migrate")
|
||||
|
||||
zerolog.SetGlobalLevel(zerolog.InfoLevel)
|
||||
|
||||
@@ -94,7 +103,7 @@ func cleanup(_ *cobra.Command, cfg *config.Config) error {
|
||||
if !ok {
|
||||
return configlog.ReturnError(errors.New("Unknown share manager type '" + driver + "'"))
|
||||
}
|
||||
mgr, err := f(rcfg[driver].(map[string]any), l)
|
||||
mgr, err := f(rcfg[driver].(map[string]any), &l)
|
||||
if err != nil {
|
||||
return configlog.ReturnError(err)
|
||||
}
|
||||
@@ -121,7 +130,11 @@ func cleanup(_ *cobra.Command, cfg *config.Config) error {
|
||||
}
|
||||
serviceUserCtx = l.WithContext(serviceUserCtx)
|
||||
|
||||
mgr.(*jsoncs3.Manager).CleanupStaleShares(serviceUserCtx)
|
||||
cleanupCtx, cancel := context.WithTimeout(serviceUserCtx, cleanupTimeout)
|
||||
defer cancel()
|
||||
if err := mgr.(*jsoncs3.Manager).CleanupStaleShares(cleanupCtx); err != nil {
|
||||
return configlog.ReturnError(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -159,20 +172,13 @@ func revaShareConfig(cfg *sharing.Config) map[string]any {
|
||||
"machine_auth_apikey": cfg.UserSharingDrivers.CS3.SystemUserAPIKey,
|
||||
},
|
||||
"jsoncs3": map[string]any{
|
||||
"gateway_addr": cfg.Reva.Address,
|
||||
"provider_addr": cfg.UserSharingDrivers.JSONCS3.ProviderAddr,
|
||||
"service_user_id": cfg.UserSharingDrivers.JSONCS3.SystemUserID,
|
||||
"service_user_idp": cfg.UserSharingDrivers.JSONCS3.SystemUserIDP,
|
||||
"machine_auth_apikey": cfg.UserSharingDrivers.JSONCS3.SystemUserAPIKey,
|
||||
"gateway_addr": cfg.Reva.Address,
|
||||
"provider_addr": cfg.UserSharingDrivers.JSONCS3.ProviderAddr,
|
||||
"system_user_id": cfg.UserSharingDrivers.JSONCS3.SystemUserID,
|
||||
"system_user_idp": cfg.UserSharingDrivers.JSONCS3.SystemUserIDP,
|
||||
"machine_auth_apikey": cfg.UserSharingDrivers.JSONCS3.SystemUserAPIKey,
|
||||
"service_account_id": cfg.ServiceAccount.ServiceAccountID,
|
||||
"service_account_secret": cfg.ServiceAccount.ServiceAccountSecret,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func logger() *zerolog.Logger {
|
||||
log := oclog.NewLogger(
|
||||
oclog.Name("migrate"),
|
||||
oclog.Level("info"),
|
||||
oclog.Pretty(true),
|
||||
oclog.Color(true)).Logger
|
||||
return &log
|
||||
}
|
||||
@@ -36,7 +36,8 @@ func TrashPurgeEmptyDirsCommand(cfg *config.Config) *cobra.Command {
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
basePath, _ := cmd.Flags().GetString("basepath")
|
||||
dryRun, _ := cmd.Flags().GetBool("dry-run")
|
||||
if err := trash.PurgeTrashEmptyPaths(basePath, dryRun); err != nil {
|
||||
posix := cfg.StorageUsers.Driver == posixDriver
|
||||
if err := trash.PurgeTrashEmptyPaths(basePath, dryRun, posix); err != nil {
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ func CreateConfig(insecure, forceOverwrite, diff bool, configPath, adminPassword
|
||||
systemUserID, adminUserID, graphApplicationID, storageUsersMountID, serviceAccountID string
|
||||
idmServicePassword, idpServicePassword, ocAdminServicePassword, revaServicePassword string
|
||||
tokenManagerJwtSecret, collaborationWOPISecret, machineAuthAPIKey, systemUserAPIKey string
|
||||
revaTransferSecret, thumbnailsTransferSecret, serviceAccountSecret, urlSigningSecret string
|
||||
revaTransferSecret, serviceAccountSecret, urlSigningSecret string
|
||||
adminPasswdwordGenerated bool
|
||||
)
|
||||
|
||||
@@ -94,7 +94,6 @@ func CreateConfig(insecure, forceOverwrite, diff bool, configPath, adminPassword
|
||||
machineAuthAPIKey = oldCfg.MachineAuthAPIKey
|
||||
systemUserAPIKey = oldCfg.SystemUserAPIKey
|
||||
revaTransferSecret = oldCfg.TransferSecret
|
||||
thumbnailsTransferSecret = oldCfg.Thumbnails.Thumbnail.TransferSecret
|
||||
serviceAccountSecret = oldCfg.Graph.ServiceAccount.ServiceAccountSecret
|
||||
urlSigningSecret = oldCfg.URLSigningSecret
|
||||
if urlSigningSecret == "" {
|
||||
@@ -155,10 +154,6 @@ func CreateConfig(insecure, forceOverwrite, diff bool, configPath, adminPassword
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not generate random secret for urlSigningSecret: %s", err)
|
||||
}
|
||||
thumbnailsTransferSecret, err = generators.GenerateRandomPassword(passwordLength)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not generate random password for thumbnailsTransferSecret: %s", err)
|
||||
}
|
||||
serviceAccountSecret, err = generators.GenerateRandomPassword(passwordLength)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not generate random secret for serviceAccountSecret: %s", err)
|
||||
@@ -230,11 +225,6 @@ func CreateConfig(insecure, forceOverwrite, diff bool, configPath, adminPassword
|
||||
},
|
||||
ServiceAccount: serviceAccount,
|
||||
},
|
||||
Thumbnails: ThumbnailService{
|
||||
Thumbnail: ThumbnailSettings{
|
||||
TransferSecret: thumbnailsTransferSecret,
|
||||
},
|
||||
},
|
||||
Gateway: Gateway{
|
||||
StorageRegistry: StorageRegistry{
|
||||
StorageUsersMountID: storageUsersMountID,
|
||||
@@ -302,9 +292,6 @@ func CreateConfig(insecure, forceOverwrite, diff bool, configPath, adminPassword
|
||||
},
|
||||
ServiceAccount: serviceAccount,
|
||||
}
|
||||
|
||||
cfg.Thumbnails.Thumbnail.WebdavAllowInsecure = true
|
||||
cfg.Thumbnails.Thumbnail.Cs3AllowInsecure = true
|
||||
}
|
||||
yamlOutput, err := yaml.Marshal(cfg)
|
||||
if err != nil {
|
||||
|
||||
@@ -33,7 +33,6 @@ type OpenCloudConfig struct {
|
||||
Users UsersAndGroupsService `yaml:"users"`
|
||||
Groups UsersAndGroupsService `yaml:"groups"`
|
||||
Ocm OcmService `yaml:"ocm"`
|
||||
Thumbnails ThumbnailService `yaml:"thumbnails"`
|
||||
Search Search `yaml:"search"`
|
||||
Audit Audit `yaml:"audit"`
|
||||
Settings SettingsService `yaml:"settings"`
|
||||
@@ -220,18 +219,6 @@ type StorageUsers struct {
|
||||
ServiceAccount ServiceAccount `yaml:"service_account"`
|
||||
}
|
||||
|
||||
// ThumbnailSettings is the configuration for the thumbnail settings
|
||||
type ThumbnailSettings struct {
|
||||
TransferSecret string `yaml:"transfer_secret"`
|
||||
WebdavAllowInsecure bool `yaml:"webdav_allow_insecure"`
|
||||
Cs3AllowInsecure bool `yaml:"cs3_allow_insecure"`
|
||||
}
|
||||
|
||||
// ThumbnailService is the configuration for the thumbnail service
|
||||
type ThumbnailService struct {
|
||||
Thumbnail ThumbnailSettings
|
||||
}
|
||||
|
||||
// TokenManager is the configuration for the token manager
|
||||
type TokenManager struct {
|
||||
JWTSecret string `yaml:"jwt_secret"`
|
||||
|
||||
@@ -389,9 +389,16 @@ func Start(ctx context.Context, o ...Option) error {
|
||||
if ev.Restarting {
|
||||
l = s.Log.Error()
|
||||
}
|
||||
l.Str("event", e.String()).Str("service", ev.ServiceName).Str("supervisor", ev.SupervisorName).
|
||||
Bool("restarting", ev.Restarting).Float64("failures", ev.CurrentFailures).Float64("threshold", ev.FailureThreshold).
|
||||
Interface("error", ev.Err).Msg("service terminated")
|
||||
l = l.Str("event", e.String()).Str("service", ev.ServiceName).Str("supervisor", ev.SupervisorName).
|
||||
Bool("restarting", ev.Restarting).Float64("failures", ev.CurrentFailures).Float64("threshold", ev.FailureThreshold)
|
||||
// ev.Err is an interface{}: marshaling an error yields {} because
|
||||
// its fields are unexported, so the message has to go through Err
|
||||
if err, ok := ev.Err.(error); ok {
|
||||
l = l.Err(err)
|
||||
} else {
|
||||
l = l.Interface("error", ev.Err)
|
||||
}
|
||||
l.Msg("service terminated")
|
||||
case suture.EventBackoff:
|
||||
s.Log.Warn().Str("event", e.String()).Str("supervisor", ev.SupervisorName).Msg("service backoff")
|
||||
case suture.EventResume:
|
||||
|
||||
@@ -10,12 +10,23 @@ import (
|
||||
const (
|
||||
// _trashGlobPattern is the glob pattern to find all trash items
|
||||
_trashGlobPattern = "spaces/*/*/trash/*/*/*/*"
|
||||
// _trashRootPattern is the glob pattern of the trash container root
|
||||
_trashRootPattern = "spaces/*/*/trash"
|
||||
// _posixTrashGlobPattern is the glob pattern to find all trash items on posix
|
||||
_posixTrashGlobPattern = "*/*/.Trash/files/*"
|
||||
// _posixTrashRootPattern is the glob pattern of the trash container root on posix
|
||||
_posixTrashRootPattern = "*/*/.Trash/files"
|
||||
)
|
||||
|
||||
// PurgeTrashEmptyPaths purges empty paths in the trash
|
||||
func PurgeTrashEmptyPaths(p string, dryRun bool) error {
|
||||
func PurgeTrashEmptyPaths(p string, dryRun bool, posix bool) error {
|
||||
pattern := _trashGlobPattern
|
||||
if posix {
|
||||
pattern = _posixTrashGlobPattern
|
||||
}
|
||||
|
||||
// we have all trash nodes in all spaces now
|
||||
dirs, err := filepath.Glob(filepath.Join(p, _trashGlobPattern))
|
||||
dirs, err := filepath.Glob(filepath.Join(p, pattern))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -25,15 +36,26 @@ func PurgeTrashEmptyPaths(p string, dryRun bool) error {
|
||||
}
|
||||
|
||||
for _, d := range dirs {
|
||||
if err := removeEmptyFolder(d, dryRun); err != nil {
|
||||
if err := removeEmptyFolder(d, dryRun, posix, p); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func removeEmptyFolder(path string, dryRun bool) error {
|
||||
func removeEmptyFolder(path string, dryRun bool, posix bool, basePath string) error {
|
||||
|
||||
if dryRun {
|
||||
if posix {
|
||||
// on posix the ".trashitem" entries are the actual data and can be
|
||||
// files, which are skipped, so we need to check here if the path
|
||||
// is the actual dir, the same check for real removal part
|
||||
fi, err := os.Stat(path)
|
||||
if err != nil || !fi.IsDir() {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
f, err := os.ReadDir(path)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -43,6 +65,14 @@ func removeEmptyFolder(path string, dryRun bool) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if posix {
|
||||
fi, err := os.Stat(path)
|
||||
if err != nil || !fi.IsDir() {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if err := os.Remove(path); err != nil {
|
||||
// we do not really care about the error here
|
||||
// if the folder is not empty we will get an error,
|
||||
@@ -50,8 +80,17 @@ func removeEmptyFolder(path string, dryRun bool) error {
|
||||
return nil
|
||||
}
|
||||
nd := filepath.Dir(path)
|
||||
if filepath.Base(nd) == "trash" {
|
||||
if isTrashRoot(nd, basePath, posix) {
|
||||
return nil
|
||||
}
|
||||
return removeEmptyFolder(nd, dryRun)
|
||||
return removeEmptyFolder(nd, dryRun, posix, basePath)
|
||||
}
|
||||
|
||||
func isTrashRoot(path, basePath string, posix bool) bool {
|
||||
rootPattern := _trashRootPattern
|
||||
if posix {
|
||||
rootPattern = _posixTrashRootPattern
|
||||
}
|
||||
matched, _ := filepath.Match(filepath.Join(basePath, rootPattern), path)
|
||||
return matched
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
package trash
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/test-go/testify/require"
|
||||
)
|
||||
|
||||
func TestIsTrashRootDecomposed(t *testing.T) {
|
||||
storageRoot := "test_temp_" + t.Name()
|
||||
defer os.RemoveAll(storageRoot)
|
||||
|
||||
require.True(t, isTrashRoot(storageRoot+"/spaces/id/id/trash", storageRoot, false))
|
||||
require.False(t, isTrashRoot(storageRoot+"/spaces/id/id/trash/s1/s2/s3/node", storageRoot, false))
|
||||
require.False(t, isTrashRoot(storageRoot+"/spaces/id/id/trash/s1/s2/trash/node", storageRoot, false))
|
||||
}
|
||||
|
||||
func TestIsTrashRootPosix(t *testing.T) {
|
||||
storageRoot := "test_temp_" + t.Name()
|
||||
defer os.RemoveAll(storageRoot)
|
||||
|
||||
require.True(t, isTrashRoot(storageRoot+"/users/alice/.Trash/files", storageRoot, true))
|
||||
require.False(t, isTrashRoot(storageRoot+"/users/alice/.Trash/files/item.trashitem", storageRoot, true))
|
||||
require.False(t, isTrashRoot(storageRoot+"/users/alice/.Trash/files/item.trashitem/files", storageRoot, true))
|
||||
}
|
||||
|
||||
func TestRemoveEmptyFolderPosix(t *testing.T) {
|
||||
storageRoot := "test_temp_" + t.Name()
|
||||
base := storageRoot + "/users/alice/.Trash/files"
|
||||
defer os.RemoveAll(storageRoot)
|
||||
|
||||
emptyChain := base + "/empty.trashitem/sub/subsub"
|
||||
require.NoError(t, os.MkdirAll(emptyChain, os.ModePerm))
|
||||
|
||||
nonEmpty := base + "/keep.trashitem"
|
||||
require.NoError(t, os.MkdirAll(nonEmpty, os.ModePerm))
|
||||
require.NoError(t, os.WriteFile(nonEmpty+"/file.txt", []byte("some text"), os.ModePerm))
|
||||
|
||||
require.NoError(t, removeEmptyFolder(emptyChain, false, true, storageRoot))
|
||||
|
||||
assertNoDirExists(t, emptyChain)
|
||||
assertNoDirExists(t, base+"/empty.trashitem")
|
||||
assertDirExists(t, base)
|
||||
assertDirExists(t, nonEmpty)
|
||||
}
|
||||
|
||||
func TestRemoveEmptyFolderPosixUserDirNamedFiles(t *testing.T) {
|
||||
storageRoot := "test_temp_" + t.Name()
|
||||
base := storageRoot + "/users/alice/.Trash/files"
|
||||
defer os.RemoveAll(storageRoot)
|
||||
|
||||
nestedFilesDir := base + "/folder.trashitem/files/files"
|
||||
require.NoError(t, os.MkdirAll(nestedFilesDir, os.ModePerm))
|
||||
|
||||
require.NoError(t, removeEmptyFolder(nestedFilesDir, false, true, storageRoot))
|
||||
|
||||
assertNoDirExists(t, nestedFilesDir)
|
||||
assertNoDirExists(t, base+"/folder.trashitem/files")
|
||||
assertNoDirExists(t, base+"/folder.trashitem")
|
||||
assertDirExists(t, base)
|
||||
}
|
||||
|
||||
func TestRemoveEmptyFolderDecomposed(t *testing.T) {
|
||||
storageRoot := "test_temp_" + t.Name()
|
||||
base := storageRoot + "/spaces/id/id/trash"
|
||||
defer os.RemoveAll(storageRoot)
|
||||
|
||||
emptyChain := base + "/s1/s2/s3/node"
|
||||
require.NoError(t, os.MkdirAll(emptyChain, os.ModePerm))
|
||||
|
||||
require.NoError(t, removeEmptyFolder(emptyChain, false, false, storageRoot))
|
||||
|
||||
assertNoDirExists(t, emptyChain)
|
||||
assertNoDirExists(t, base+"/s1/s2/s3")
|
||||
assertNoDirExists(t, base+"/s1/s2")
|
||||
assertNoDirExists(t, base+"/s1")
|
||||
assertDirExists(t, base)
|
||||
}
|
||||
|
||||
func TestRemoveEmptyFolderDecomposedUserDirNamedTrash(t *testing.T) {
|
||||
storageRoot := "test_temp_" + t.Name()
|
||||
base := storageRoot + "/spaces/id/id/trash"
|
||||
defer os.RemoveAll(storageRoot)
|
||||
|
||||
nestedTrashDir := base + "/s1/trash/s2/node"
|
||||
require.NoError(t, os.MkdirAll(nestedTrashDir, os.ModePerm))
|
||||
|
||||
require.NoError(t, removeEmptyFolder(nestedTrashDir, false, false, storageRoot))
|
||||
|
||||
assertNoDirExists(t, nestedTrashDir)
|
||||
assertNoDirExists(t, base+"/s1/trash/s2")
|
||||
assertNoDirExists(t, base+"/s1/trash")
|
||||
assertNoDirExists(t, base+"/s1")
|
||||
assertDirExists(t, base)
|
||||
}
|
||||
|
||||
func assertNoDirExists(t *testing.T, path string) {
|
||||
t.Helper()
|
||||
_, err := os.Stat(path)
|
||||
require.True(t, os.IsNotExist(err))
|
||||
}
|
||||
|
||||
func assertDirExists(t *testing.T, path string) {
|
||||
t.Helper()
|
||||
fi, err := os.Stat(path)
|
||||
require.NoError(t, err)
|
||||
require.True(t, fi.IsDir())
|
||||
}
|
||||
@@ -86,5 +86,6 @@
|
||||
<property name="lineLimit" value="120" />
|
||||
<property name="absoluteLineLimit" value="120" />
|
||||
</properties>
|
||||
<exclude-pattern>*/tests/acceptance/bootstrap/*</exclude-pattern>
|
||||
</rule>
|
||||
</ruleset>
|
||||
@@ -43,6 +43,10 @@ type StringNode struct {
|
||||
*Base
|
||||
Key string
|
||||
Value string
|
||||
Exact bool
|
||||
// CaseInsensitive marks a case-insensitive restriction; set by the search
|
||||
// lowering pass, a backend routes it to the field's lowercased form.
|
||||
CaseInsensitive bool
|
||||
}
|
||||
|
||||
// BooleanNode represents a bool value
|
||||
@@ -60,6 +64,14 @@ type DateTimeNode struct {
|
||||
Value time.Time
|
||||
}
|
||||
|
||||
// NumberNode represents a numeric value
|
||||
type NumberNode struct {
|
||||
*Base
|
||||
Key string
|
||||
Operator *OperatorNode
|
||||
Value float64
|
||||
}
|
||||
|
||||
// OperatorNode represents an operator value like
|
||||
// AND, OR, NOT, =, <= ... and so on
|
||||
type OperatorNode struct {
|
||||
|
||||
@@ -21,6 +21,7 @@ func DiffAst(x, y any, opts ...cmp.Option) string {
|
||||
cmpopts.IgnoreFields(ast.GroupNode{}, "Base"),
|
||||
cmpopts.IgnoreFields(ast.BooleanNode{}, "Base"),
|
||||
cmpopts.IgnoreFields(ast.DateTimeNode{}, "Base"),
|
||||
cmpopts.IgnoreFields(ast.NumberNode{}, "Base"),
|
||||
)...,
|
||||
)
|
||||
}
|
||||
@@ -14,5 +14,17 @@ func DefaultApp(app *cobra.Command) *cobra.Command {
|
||||
// version info
|
||||
app.Version = fmt.Sprintf("%s (%s <%s>) (%s)", version.String, "OpenCloud GmbH", "support@opencloud.eu", version.Compiled())
|
||||
|
||||
// cobra would print the error on top of what main() already prints
|
||||
app.SilenceErrors = true
|
||||
|
||||
// keep the usage block for flag parse errors, drop it once RunE runs.
|
||||
// Traversing runs the hook even below a subcommand that brings its own,
|
||||
// e.g. every service below ServiceCommand.
|
||||
cobra.EnableTraverseRunHooks = true
|
||||
app.PersistentPreRunE = func(cmd *cobra.Command, _ []string) error {
|
||||
cmd.SilenceUsage = true
|
||||
return nil
|
||||
}
|
||||
|
||||
return app
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package events
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
)
|
||||
|
||||
type ResourceMention struct {
|
||||
Executant *user.UserId
|
||||
UserIDs []*user.UserId
|
||||
Ref *provider.Reference
|
||||
Timestamp time.Time
|
||||
}
|
||||
|
||||
func (ResourceMention) Unmarshal(v []byte) (interface{}, error) {
|
||||
e := ResourceMention{}
|
||||
err := json.Unmarshal(v, &e)
|
||||
return e, err
|
||||
}
|
||||
+12
-3
@@ -2,11 +2,11 @@ package kql
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/jinzhu/now"
|
||||
"github.com/opencloud-eu/opencloud/pkg/ast"
|
||||
"github.com/opencloud-eu/opencloud/services/search/pkg/query"
|
||||
)
|
||||
|
||||
func toNode[T ast.Node](in any) (T, error) {
|
||||
@@ -84,7 +84,7 @@ func toTimeRange(in any) (*time.Time, *time.Time, error) {
|
||||
|
||||
value, err := toString(in)
|
||||
if err != nil {
|
||||
return &from, &to, &query.UnsupportedTimeRangeError{}
|
||||
return &from, &to, &UnsupportedTimeRangeError{}
|
||||
}
|
||||
|
||||
c := &now.Config{
|
||||
@@ -131,8 +131,17 @@ func toTimeRange(in any) (*time.Time, *time.Time, error) {
|
||||
}
|
||||
|
||||
if from.IsZero() || to.IsZero() {
|
||||
return nil, nil, &query.UnsupportedTimeRangeError{}
|
||||
return nil, nil, &UnsupportedTimeRangeError{}
|
||||
}
|
||||
|
||||
return &from, &to, nil
|
||||
}
|
||||
|
||||
func toFloat(v any) (float64, error) {
|
||||
value, err := toString(v)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return strconv.ParseFloat(value, 64)
|
||||
}
|
||||
+23
-4
@@ -40,6 +40,7 @@ GroupNode <-
|
||||
PropertyRestrictionNodes <-
|
||||
YesNoPropertyRestrictionNode /
|
||||
DateTimeRestrictionNode /
|
||||
NumberRestrictionNode /
|
||||
TextPropertyRestrictionNode
|
||||
|
||||
YesNoPropertyRestrictionNode <-
|
||||
@@ -69,9 +70,22 @@ DateTimeRestrictionNode <-
|
||||
return buildNaturalLanguageDateTimeNodes(k, v, c.text, c.pos)
|
||||
}
|
||||
|
||||
NumberRestrictionNode <-
|
||||
k:Key o:(
|
||||
OperatorGreaterOrEqualNode /
|
||||
OperatorLessOrEqualNode /
|
||||
OperatorGreaterNode /
|
||||
OperatorLessNode
|
||||
) '"'? v:Number '"'? {
|
||||
return buildNumberNode(k, o, v, c.text, c.pos)
|
||||
}
|
||||
|
||||
TextPropertyRestrictionNode <-
|
||||
k:Key (OperatorColonNode / OperatorEqualNode) v:(String / [^ ()]+){
|
||||
return buildStringNode(k, v, c.text, c.pos)
|
||||
k:Key OperatorEqualNode v:(String / [^ ()]+) {
|
||||
return buildStringNode(k, v, true, c.text, c.pos)
|
||||
} /
|
||||
k:Key OperatorColonNode v:(String / [^ ()]+) {
|
||||
return buildStringNode(k, v, false, c.text, c.pos)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
@@ -84,12 +98,12 @@ FreeTextKeywordNodes <-
|
||||
|
||||
PhraseNode <-
|
||||
OperatorColonNode? _ v:String _ OperatorColonNode? {
|
||||
return buildStringNode("", v, c.text, c.pos)
|
||||
return buildStringNode("", v, false, c.text, c.pos)
|
||||
}
|
||||
|
||||
WordNode <-
|
||||
OperatorColonNode? _ v:[^ :()]+ _ OperatorColonNode? {
|
||||
return buildStringNode("", v, c.text, c.pos)
|
||||
return buildStringNode("", v, false, c.text, c.pos)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
@@ -229,6 +243,11 @@ String <-
|
||||
return v, nil
|
||||
}
|
||||
|
||||
Number <-
|
||||
[0-9]+ ("." [0-9]+)? {
|
||||
return string(c.text), nil
|
||||
}
|
||||
|
||||
Digit <-
|
||||
[0-9] {
|
||||
return c.text, nil
|
||||
|
||||
+928
-483
File diff suppressed because it is too large.
Load diff
+80
-11
@@ -9,7 +9,6 @@ import (
|
||||
"github.com/opencloud-eu/opencloud/pkg/ast"
|
||||
"github.com/opencloud-eu/opencloud/pkg/ast/test"
|
||||
"github.com/opencloud-eu/opencloud/pkg/kql"
|
||||
"github.com/opencloud-eu/opencloud/services/search/pkg/query"
|
||||
tAssert "github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -34,13 +33,13 @@ func TestParse_Spec(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: `AND`,
|
||||
error: query.StartsWithBinaryOperatorError{
|
||||
error: kql.StartsWithBinaryOperatorError{
|
||||
Node: &ast.OperatorNode{Value: kql.BoolAND},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: `AND cat AND dog`,
|
||||
error: query.StartsWithBinaryOperatorError{
|
||||
error: kql.StartsWithBinaryOperatorError{
|
||||
Node: &ast.OperatorNode{Value: kql.BoolAND},
|
||||
},
|
||||
},
|
||||
@@ -80,13 +79,13 @@ func TestParse_Spec(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: `OR`,
|
||||
error: query.StartsWithBinaryOperatorError{
|
||||
error: kql.StartsWithBinaryOperatorError{
|
||||
Node: &ast.OperatorNode{Value: kql.BoolOR},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: `OR cat AND dog`,
|
||||
error: query.StartsWithBinaryOperatorError{
|
||||
error: kql.StartsWithBinaryOperatorError{
|
||||
Node: &ast.OperatorNode{Value: kql.BoolOR},
|
||||
},
|
||||
},
|
||||
@@ -145,6 +144,22 @@ func TestParse_Spec(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: `author="John Smith"`,
|
||||
ast: &ast.Ast{
|
||||
Nodes: []ast.Node{
|
||||
&ast.StringNode{Key: "author", Value: "John Smith", Exact: true},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: `filename=budget.xlsx`,
|
||||
ast: &ast.Ast{
|
||||
Nodes: []ast.Node{
|
||||
&ast.StringNode{Key: "filename", Value: "budget.xlsx", Exact: true},
|
||||
},
|
||||
},
|
||||
},
|
||||
// 3.2.3 Implicit Operator for Property Restriction
|
||||
{
|
||||
name: `author:"John Smith" filetype:docx`,
|
||||
@@ -423,6 +438,60 @@ func TestParse_Spec(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestParse_NumberRestrictionNode(t *testing.T) {
|
||||
tests := []testCase{
|
||||
{
|
||||
name: "format",
|
||||
query: join([]string{
|
||||
`size>100`,
|
||||
`size>"100"`,
|
||||
`size>=15.5`,
|
||||
`size<100`,
|
||||
`size<=100`,
|
||||
}),
|
||||
ast: &ast.Ast{
|
||||
Nodes: []ast.Node{
|
||||
&ast.NumberNode{
|
||||
Key: "size",
|
||||
Operator: &ast.OperatorNode{Value: ">"},
|
||||
Value: 100,
|
||||
},
|
||||
&ast.OperatorNode{Value: kql.BoolAND},
|
||||
&ast.NumberNode{
|
||||
Key: "size",
|
||||
Operator: &ast.OperatorNode{Value: ">"},
|
||||
Value: 100,
|
||||
},
|
||||
&ast.OperatorNode{Value: kql.BoolAND},
|
||||
&ast.NumberNode{
|
||||
Key: "size",
|
||||
Operator: &ast.OperatorNode{Value: ">="},
|
||||
Value: 15.5,
|
||||
},
|
||||
&ast.OperatorNode{Value: kql.BoolAND},
|
||||
&ast.NumberNode{
|
||||
Key: "size",
|
||||
Operator: &ast.OperatorNode{Value: "<"},
|
||||
Value: 100,
|
||||
},
|
||||
&ast.OperatorNode{Value: kql.BoolAND},
|
||||
&ast.NumberNode{
|
||||
Key: "size",
|
||||
Operator: &ast.OperatorNode{Value: "<="},
|
||||
Value: 100,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
testKQL(t, tc)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParse_DateTimeRestrictionNode(t *testing.T) {
|
||||
tests := []testCase{
|
||||
{
|
||||
@@ -860,37 +929,37 @@ func TestParse_Errors(t *testing.T) {
|
||||
tests := []testCase{
|
||||
{
|
||||
query: "animal:(mammal:cat mammal:dog reptile:turtle)",
|
||||
error: query.NamedGroupInvalidNodesError{
|
||||
error: kql.NamedGroupInvalidNodesError{
|
||||
Node: &ast.StringNode{Key: "mammal", Value: "cat"},
|
||||
},
|
||||
},
|
||||
{
|
||||
query: "animal:(cat mammal:dog turtle)",
|
||||
error: query.NamedGroupInvalidNodesError{
|
||||
error: kql.NamedGroupInvalidNodesError{
|
||||
Node: &ast.StringNode{Key: "mammal", Value: "dog"},
|
||||
},
|
||||
},
|
||||
{
|
||||
query: "animal:(AND cat)",
|
||||
error: query.StartsWithBinaryOperatorError{
|
||||
error: kql.StartsWithBinaryOperatorError{
|
||||
Node: &ast.OperatorNode{Value: kql.BoolAND},
|
||||
},
|
||||
},
|
||||
{
|
||||
query: "animal:(OR cat)",
|
||||
error: query.StartsWithBinaryOperatorError{
|
||||
error: kql.StartsWithBinaryOperatorError{
|
||||
Node: &ast.OperatorNode{Value: kql.BoolOR},
|
||||
},
|
||||
},
|
||||
{
|
||||
query: "(AND cat)",
|
||||
error: query.StartsWithBinaryOperatorError{
|
||||
error: kql.StartsWithBinaryOperatorError{
|
||||
Node: &ast.OperatorNode{Value: kql.BoolAND},
|
||||
},
|
||||
},
|
||||
{
|
||||
query: "(OR cat)",
|
||||
error: query.StartsWithBinaryOperatorError{
|
||||
error: kql.StartsWithBinaryOperatorError{
|
||||
Node: &ast.OperatorNode{Value: kql.BoolOR},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
package kql
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// PatchTimeNow is here to patch the package time now func,
|
||||
// which is used in the test suite
|
||||
func PatchTimeNow(t func() time.Time) {
|
||||
timeNow = t
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package query
|
||||
package kql
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/opencloud-eu/opencloud/pkg/ast"
|
||||
@@ -38,10 +39,17 @@ func (e UnsupportedTimeRangeError) Error() string {
|
||||
return fmt.Sprintf("unable to convert '%v' to a time range", e.Value)
|
||||
}
|
||||
|
||||
// IsValidationError reports whether err is one of the KQL parse/validation
|
||||
// errors produced by this package, i.e. the query itself is at fault and the
|
||||
// caller should treat it as a bad request.
|
||||
func IsValidationError(err error) bool {
|
||||
switch err.(type) {
|
||||
case *StartsWithBinaryOperatorError, *NamedGroupInvalidNodesError, *UnsupportedTimeRangeError:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
var (
|
||||
startsWithBinaryOperator *StartsWithBinaryOperatorError
|
||||
namedGroupInvalidNodes *NamedGroupInvalidNodesError
|
||||
unsupportedTimeRange *UnsupportedTimeRangeError
|
||||
)
|
||||
|
||||
return errors.As(err, &startsWithBinaryOperator) ||
|
||||
errors.As(err, &namedGroupInvalidNodes) ||
|
||||
errors.As(err, &unsupportedTimeRange)
|
||||
}
|
||||
+32
-1
@@ -50,7 +50,7 @@ func buildAST(n any, text []byte, pos position) (*ast.Ast, error) {
|
||||
return a, nil
|
||||
}
|
||||
|
||||
func buildStringNode(k, v any, text []byte, pos position) (*ast.StringNode, error) {
|
||||
func buildStringNode(k, v any, exact bool, text []byte, pos position) (*ast.StringNode, error) {
|
||||
b, err := base(text, pos)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -70,6 +70,7 @@ func buildStringNode(k, v any, text []byte, pos position) (*ast.StringNode, erro
|
||||
Base: b,
|
||||
Key: key,
|
||||
Value: value,
|
||||
Exact: exact,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -101,6 +102,36 @@ func buildDateTimeNode(k, o, v any, text []byte, pos position) (*ast.DateTimeNod
|
||||
Value: value,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func buildNumberNode(k, o, v any, text []byte, pos position) (*ast.NumberNode, error) {
|
||||
b, err := base(text, pos)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
operator, err := toNode[*ast.OperatorNode](o)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
key, err := toString(k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
value, err := toFloat(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &ast.NumberNode{
|
||||
Base: b,
|
||||
Key: key,
|
||||
Operator: operator,
|
||||
Value: value,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func buildNaturalLanguageDateTimeNodes(k, v any, text []byte, pos position) ([]ast.Node, error) {
|
||||
b, err := base(text, pos)
|
||||
if err != nil {
|
||||
|
||||
@@ -47,3 +47,9 @@ func (b Builder) Build(q string) (*ast.Ast, error) {
|
||||
// timeNow mirrors time.Now by default, the only reason why this exists
|
||||
// is to monkey patch it from the tests. See PatchTimeNow
|
||||
var timeNow = time.Now
|
||||
|
||||
// PatchTimeNow pins the clock the natural language dates resolve against,
|
||||
// so a test can hold "today" still while it runs
|
||||
func PatchTimeNow(t func() time.Time) {
|
||||
timeNow = t
|
||||
}
|
||||
+1
-2
@@ -5,7 +5,6 @@ import (
|
||||
|
||||
"github.com/opencloud-eu/opencloud/pkg/ast"
|
||||
"github.com/opencloud-eu/opencloud/pkg/kql"
|
||||
"github.com/opencloud-eu/opencloud/services/search/pkg/query"
|
||||
tAssert "github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -22,7 +21,7 @@ func TestNewAST(t *testing.T) {
|
||||
{
|
||||
name: "error",
|
||||
givenQuery: kql.BoolAND,
|
||||
expectedError: query.StartsWithBinaryOperatorError{
|
||||
expectedError: kql.StartsWithBinaryOperatorError{
|
||||
Node: &ast.OperatorNode{Value: kql.BoolAND},
|
||||
},
|
||||
},
|
||||
|
||||
+3
-4
@@ -2,7 +2,6 @@ package kql
|
||||
|
||||
import (
|
||||
"github.com/opencloud-eu/opencloud/pkg/ast"
|
||||
"github.com/opencloud-eu/opencloud/services/search/pkg/query"
|
||||
)
|
||||
|
||||
func validateAst(a *ast.Ast) error {
|
||||
@@ -10,7 +9,7 @@ func validateAst(a *ast.Ast) error {
|
||||
case *ast.OperatorNode:
|
||||
switch node.Value {
|
||||
case BoolAND, BoolOR:
|
||||
return &query.StartsWithBinaryOperatorError{Node: node}
|
||||
return &StartsWithBinaryOperatorError{Node: node}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -21,14 +20,14 @@ func validateGroupNode(n *ast.GroupNode) error {
|
||||
case *ast.OperatorNode:
|
||||
switch node.Value {
|
||||
case BoolAND, BoolOR:
|
||||
return &query.StartsWithBinaryOperatorError{Node: node}
|
||||
return &StartsWithBinaryOperatorError{Node: node}
|
||||
}
|
||||
}
|
||||
|
||||
if n.Key != "" {
|
||||
for _, node := range n.Nodes {
|
||||
if ast.NodeKey(node) != "" {
|
||||
return &query.NamedGroupInvalidNodesError{Node: node}
|
||||
return &NamedGroupInvalidNodesError{Node: node}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/opencloud-eu/opencloud/pkg/log"
|
||||
"github.com/opencloud-eu/opencloud/pkg/version"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
type BuildInfoMetric = *prometheus.GaugeVec
|
||||
|
||||
// Create a BuildInfo metric for the specified namespace and subsystem.
|
||||
func BuildInfo(namespace, subsystem string) BuildInfoMetric {
|
||||
return prometheus.NewGaugeVec(prometheus.GaugeOpts{
|
||||
Namespace: namespace,
|
||||
Subsystem: subsystem,
|
||||
Name: "build_info",
|
||||
Help: "Build information",
|
||||
}, []string{"version"})
|
||||
}
|
||||
|
||||
// Determine the fully qualified name of a metric.
|
||||
//
|
||||
// Beware that this requires storing a value into the metric in order to make it
|
||||
// visible in a temporary registry.
|
||||
// If the metric is a MetricVec, it will be Reset().
|
||||
func describe(metric prometheus.Collector, initialize func() error) (string, error) {
|
||||
reg := prometheus.NewRegistry()
|
||||
if err := reg.Register(metric); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err := initialize(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if resettable, ok := metric.(*prometheus.MetricVec); ok {
|
||||
defer resettable.Reset()
|
||||
}
|
||||
fams, err := reg.Gather()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(fams) == 0 {
|
||||
return "", fmt.Errorf("no metric families gathered")
|
||||
}
|
||||
return fams[0].GetName(), nil
|
||||
}
|
||||
|
||||
// Take a struct that contains metrics as attributes and register all of them
|
||||
// with the specified Registerer.
|
||||
func RegisterAll(registerer prometheus.Registerer, m any, logger *log.Logger) error {
|
||||
// we go over all of them, use this to keep track of succeesses and failures
|
||||
total := 0
|
||||
succeeded := []string{}
|
||||
failed := map[string]error{}
|
||||
|
||||
// we need to use reflection here to iterate over the public metric attributes
|
||||
// that are contained in it
|
||||
r := reflect.ValueOf(m)
|
||||
if r.Kind() == reflect.Pointer {
|
||||
r = r.Elem()
|
||||
}
|
||||
|
||||
for i := 0; i < r.NumField(); i++ {
|
||||
t := r.Type().Field(i)
|
||||
n := t.Name // the name of the attribute (not the name of the metric)
|
||||
f := r.Field(i)
|
||||
if !f.CanInterface() {
|
||||
continue // we won't be able to process that one, most probably because it's not exported
|
||||
}
|
||||
v := f.Interface()
|
||||
switch c := v.(type) {
|
||||
case prometheus.Collector:
|
||||
total++
|
||||
if err := registerer.Register(c); err != nil {
|
||||
switch err.(type) {
|
||||
case prometheus.AlreadyRegisteredError:
|
||||
// silently ignore this error, as this case can happen when the suture service decides to restart
|
||||
err = nil
|
||||
succeeded = append(succeeded, n)
|
||||
default:
|
||||
failed[n] = err
|
||||
}
|
||||
} else {
|
||||
succeeded = append(succeeded, n)
|
||||
|
||||
// special post-treatment for the BuildInfo metric, as we have that one pretty much
|
||||
// everywhere: set its value with the current version so we don't need to do that every time
|
||||
switch buildInfo := c.(type) {
|
||||
case BuildInfoMetric:
|
||||
if name, err := describe(buildInfo, func() error { buildInfo.WithLabelValues("0").Set(0.0); return nil }); err != nil {
|
||||
failed[n] = err
|
||||
} else if strings.HasSuffix(name, "_build_info") {
|
||||
buildInfo.Reset()
|
||||
buildInfo.WithLabelValues(version.GetString()).Set(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
case *prometheus.Desc,
|
||||
prometheus.GaugeOpts,
|
||||
prometheus.CounterOpts,
|
||||
prometheus.HistogramOpts,
|
||||
prometheus.SummaryOpts,
|
||||
prometheus.UntypedOpts:
|
||||
// skip these
|
||||
default:
|
||||
failed[n] = fmt.Errorf("unsupported metric '%s' of type %T", n, c)
|
||||
}
|
||||
}
|
||||
if len(failed) > 0 {
|
||||
failedMsgs := []string{}
|
||||
for name, err := range failed {
|
||||
failedMsgs = append(failedMsgs, fmt.Sprintf("'%s' (%v)", name, err))
|
||||
}
|
||||
msg := strings.Join(failedMsgs, ", ")
|
||||
if logger != nil {
|
||||
logger.Warn().Msgf("registered %d/%d metrics successfully (%d failed): %s", len(succeeded), total, len(failed), msg)
|
||||
}
|
||||
return fmt.Errorf("failed to register metrics: %s", msg)
|
||||
} else {
|
||||
if logger != nil {
|
||||
logger.Debug().Msgf("registered %d/%d metrics successfully (%d failed)", len(succeeded), total, len(failed))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Register all the metrics that are contained as public attributes in the struct,
|
||||
// and log any errors that might occur while doing so.
|
||||
func Register[M any](reg prometheus.Registerer, m M, logger *log.Logger) (M, error) {
|
||||
lr := NewLoggingPrometheusRegisterer(reg, logger)
|
||||
err := RegisterAll(lr, m, logger)
|
||||
return m, err
|
||||
}
|
||||
|
||||
// Register a single metric.
|
||||
func RegisterMetric[M prometheus.Collector](reg prometheus.Registerer, m M, logger *log.Logger) error {
|
||||
return NewLoggingPrometheusRegisterer(reg, logger).Register(m)
|
||||
}
|
||||
|
||||
// Prometheus Registerer wrapper that logs every error that occurs when registering
|
||||
// a metric, and delegates to an actual Registerer.
|
||||
type LoggingPrometheusRegisterer struct {
|
||||
delegate prometheus.Registerer
|
||||
logger *log.Logger
|
||||
}
|
||||
|
||||
// Instantiate a Prometheus Registerer wrapper that logs every error that occurs when registering
|
||||
// a metric, and that delegates to an actual Registerer specified here.
|
||||
func NewLoggingPrometheusRegisterer(delegate prometheus.Registerer, logger *log.Logger) *LoggingPrometheusRegisterer {
|
||||
return &LoggingPrometheusRegisterer{
|
||||
delegate: delegate,
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *LoggingPrometheusRegisterer) Register(c prometheus.Collector) error {
|
||||
err := r.delegate.Register(c)
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
case prometheus.AlreadyRegisteredError:
|
||||
// silently ignore this error, as this case can happen when the suture service decides to restart
|
||||
err = nil
|
||||
default:
|
||||
if r.logger != nil {
|
||||
r.logger.Warn().Err(err).Msgf("failed to register metric")
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *LoggingPrometheusRegisterer) MustRegister(collectors ...prometheus.Collector) {
|
||||
for _, c := range collectors {
|
||||
if err := r.Register(c); err != nil {
|
||||
if r.logger != nil {
|
||||
r.logger.Error().Err(err).Msg("failed to register metrics collector")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *LoggingPrometheusRegisterer) Unregister(c prometheus.Collector) bool {
|
||||
return r.delegate.Unregister(c)
|
||||
}
|
||||
|
||||
var _ prometheus.Registerer = &LoggingPrometheusRegisterer{}
|
||||
@@ -0,0 +1,153 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand/v2"
|
||||
"testing"
|
||||
|
||||
"github.com/opencloud-eu/opencloud/pkg/log"
|
||||
"github.com/opencloud-eu/opencloud/pkg/version"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func randName() string {
|
||||
const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
n := 8 + rand.IntN(33)
|
||||
b := make([]byte, n)
|
||||
for i := range b {
|
||||
b[i] = letterBytes[rand.IntN(len(letterBytes))]
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func TestBuildInfo(t *testing.T) {
|
||||
require := require.New(t)
|
||||
|
||||
namespace := "name-" + randName()
|
||||
subsystem := "sub-" + randName()
|
||||
expectedName := fmt.Sprintf("%s_%s_build_info", namespace, subsystem)
|
||||
version := fmt.Sprintf("%d.%d.%d", rand.IntN(10), rand.IntN(10), rand.IntN(10))
|
||||
|
||||
g := BuildInfo(namespace, subsystem)
|
||||
reg := prometheus.NewRegistry()
|
||||
require.NoError(reg.Register(g))
|
||||
|
||||
{
|
||||
mfs, err := reg.Gather()
|
||||
require.NoError(err)
|
||||
require.Len(mfs, 0)
|
||||
}
|
||||
|
||||
g.WithLabelValues(version).Set(1)
|
||||
{
|
||||
mfs, err := reg.Gather()
|
||||
require.NoError(err)
|
||||
found := false
|
||||
for _, mf := range mfs {
|
||||
if mf.GetName() == expectedName {
|
||||
found = true
|
||||
ms := mf.GetMetric()
|
||||
require.Len(ms, 1)
|
||||
labels := ms[0].GetLabel()
|
||||
require.Len(labels, 1)
|
||||
require.NotNil(labels[0].Name)
|
||||
require.Equal("version", *labels[0].Name)
|
||||
require.NotNil(labels[0].Value)
|
||||
require.Equal(version, *labels[0].Value)
|
||||
require.Equal(1.0, ms[0].GetGauge().GetValue())
|
||||
} else {
|
||||
t.Fatalf("unexpected metric family %q", mf.GetName())
|
||||
}
|
||||
}
|
||||
require.True(found, "failed to find metric %q", expectedName)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegisterAll(t *testing.T) {
|
||||
require := require.New(t)
|
||||
|
||||
reg := prometheus.NewRegistry()
|
||||
logger := log.NewLogger()
|
||||
namespace := "name-" + randName()
|
||||
subsystem := "sub-" + randName()
|
||||
|
||||
m := struct {
|
||||
BuildInfo *prometheus.GaugeVec
|
||||
Foo *prometheus.GaugeVec
|
||||
Bar prometheus.Counter
|
||||
}{
|
||||
BuildInfo: BuildInfo(namespace, subsystem),
|
||||
Foo: prometheus.NewGaugeVec(prometheus.GaugeOpts{
|
||||
Namespace: namespace,
|
||||
Subsystem: subsystem,
|
||||
Name: "foo",
|
||||
ConstLabels: prometheus.Labels{
|
||||
"f": "oo",
|
||||
"fo": "o",
|
||||
},
|
||||
}, []string{"oof"}),
|
||||
Bar: prometheus.NewCounter(prometheus.CounterOpts{
|
||||
Namespace: namespace,
|
||||
Subsystem: subsystem,
|
||||
Name: "bar",
|
||||
}),
|
||||
}
|
||||
|
||||
expectedNameForBuildInfo := namespace + "_" + subsystem + "_build_info"
|
||||
expectedNameForFoo := namespace + "_" + subsystem + "_foo"
|
||||
expectedNameForBar := namespace + "_" + subsystem + "_bar"
|
||||
|
||||
{
|
||||
mfs, err := reg.Gather()
|
||||
require.NoError(err)
|
||||
require.Len(mfs, 0)
|
||||
}
|
||||
require.NoError(RegisterAll(reg, m, &logger))
|
||||
{
|
||||
mfs, err := reg.Gather()
|
||||
require.NoError(err)
|
||||
require.Len(mfs, 3)
|
||||
found := 0
|
||||
for _, mf := range mfs {
|
||||
switch mf.GetName() {
|
||||
case expectedNameForBuildInfo:
|
||||
found++
|
||||
ms := mf.GetMetric()
|
||||
require.Len(ms, 1)
|
||||
labels := ms[0].GetLabel()
|
||||
require.Len(labels, 1)
|
||||
require.NotNil(labels[0].Name)
|
||||
require.Equal("version", *labels[0].Name)
|
||||
require.NotNil(labels[0].Value)
|
||||
require.Equal(version.GetString(), *labels[0].Value)
|
||||
require.Equal(1.0, ms[0].GetGauge().GetValue())
|
||||
case expectedNameForFoo:
|
||||
found++
|
||||
ms := mf.GetMetric()
|
||||
require.Len(ms, 1)
|
||||
labels := ms[0].GetLabel()
|
||||
require.Len(labels, 3)
|
||||
require.NotNil(labels[0].Name)
|
||||
require.Equal("f", *labels[0].Name)
|
||||
require.NotNil(labels[0].Value)
|
||||
require.Equal("oo", *labels[0].Value)
|
||||
require.NotNil(labels[1].Name)
|
||||
require.Equal("fo", *labels[1].Name)
|
||||
require.NotNil(labels[1].Value)
|
||||
require.Equal("o", *labels[1].Value)
|
||||
require.Equal(0.0, ms[0].GetGauge().GetValue())
|
||||
case expectedNameForBar:
|
||||
found++
|
||||
ms := mf.GetMetric()
|
||||
require.Len(ms, 1)
|
||||
labels := ms[0].GetLabel()
|
||||
require.Len(labels, 0)
|
||||
require.Equal(0.0, ms[0].GetGauge().GetValue())
|
||||
default:
|
||||
t.Fatalf("unexpected metric family %q", mf.GetName())
|
||||
}
|
||||
}
|
||||
require.Equal(3, found, "failed to find expected metrics")
|
||||
}
|
||||
}
|
||||
+11
-1
@@ -2,6 +2,7 @@ package middleware
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -61,7 +62,10 @@ func OidcAuth(opts ...Option) func(http.Handler) http.Handler {
|
||||
provider, err = providerFunc()
|
||||
}
|
||||
initializeProviderLock.Unlock()
|
||||
if err != nil {
|
||||
if err != nil || provider == nil {
|
||||
if err == nil {
|
||||
err = errors.New("OIDC provider initialization returned nil")
|
||||
}
|
||||
opt.Logger.Error().Err(err).Msg("could not initialize OIDC provider")
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
@@ -82,6 +86,12 @@ func OidcAuth(opts ...Option) func(http.Handler) http.Handler {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
if userInfo == nil {
|
||||
opt.Logger.Error().Msg("OIDC provider returned empty user info")
|
||||
w.Header().Add("WWW-Authenticate", `Bearer`)
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
claims := map[string]any{}
|
||||
err = userInfo.Claims(&claims)
|
||||
if err != nil {
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package nats
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
|
||||
"github.com/nats-io/nats.go"
|
||||
)
|
||||
|
||||
func Secure(enableTLS, insecure bool, rootCA string) nats.Option {
|
||||
if enableTLS {
|
||||
if rootCA != "" {
|
||||
return nats.RootCAs(rootCA)
|
||||
}
|
||||
return nats.Secure(&tls.Config{
|
||||
MinVersion: tls.VersionTLS12,
|
||||
InsecureSkipVerify: insecure,
|
||||
})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -101,3 +101,11 @@ func MissingURLSigningSecret(service string) error {
|
||||
"the config/corresponding environment variable).",
|
||||
service, defaults.BaseConfigPath())
|
||||
}
|
||||
|
||||
func AllComponentsDisabledError(service string) error {
|
||||
return fmt.Errorf("All request handlers and event consumers are disabled for %s; at least one component must be enabled."+
|
||||
"Make sure your %s config contains the proper values "+
|
||||
"(e.g. by using 'opencloud init --diff' and applying the patch or setting a value manually in "+
|
||||
"the config/corresponding environment variable).",
|
||||
service, defaults.BaseConfigPath())
|
||||
}
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
// we init the memlimit here to include it for OpenCloud als well as individual service binaries
|
||||
func init() {
|
||||
slog.SetLogLoggerLevel(slog.LevelError)
|
||||
_, _ = memlimit.SetGoMemLimitWithOpts(
|
||||
_, _ = memlimit.Set(
|
||||
memlimit.WithLogger(slog.Default()),
|
||||
)
|
||||
}
|
||||
@@ -48,14 +48,17 @@ type HTTPServiceTLS struct {
|
||||
}
|
||||
|
||||
type Cache struct {
|
||||
Store string `yaml:"store" env:"OC_CACHE_STORE" desc:"The type of the cache store. Supported values are: 'memory', 'redis-sentinel', 'nats-js-kv', 'noop'. See the text description for details." introductionVersion:"1.0.0"`
|
||||
Nodes []string `yaml:"nodes" env:"OC_CACHE_STORE_NODES" desc:"A comma separated list of nodes to access the configured store. This has no effect when 'memory' store is configured. Note that the behaviour how nodes are used is dependent on the library of the configured store." introductionVersion:"1.0.0"`
|
||||
Database string `yaml:"database" env:"OC_CACHE_STORE_DATABASE" desc:"The database name the configured store should use." introductionVersion:"1.0.0"`
|
||||
Table string `yaml:"table" env:"OC_CACHE_STORE_TABLE" desc:"The database table the store should use." introductionVersion:"1.0.0"`
|
||||
TTL time.Duration `yaml:"ttl" env:"OC_CACHE_TTL" desc:"Time to live for events in the store. The duration can be set as number followed by a unit identifier like s, m or h." introductionVersion:"1.0.0"`
|
||||
DisablePersistence bool `yaml:"disable_persistence" env:"OC_CACHE_DISABLE_PERSISTENCE" desc:"Disables persistence of the cache. Only applies when store type 'nats-js-kv' is configured. Defaults to false." introductionVersion:"1.0.0"`
|
||||
AuthUsername string `yaml:"auth_username" env:"OC_CACHE_AUTH_USERNAME" desc:"The username to use for authentication. Only applies when store type 'nats-js-kv' is configured." introductionVersion:"1.0.0"`
|
||||
AuthPassword string `yaml:"auth_password" env:"OC_CACHE_AUTH_PASSWORD" desc:"The password to use for authentication. Only applies when store type 'nats-js-kv' is configured." introductionVersion:"1.0.0"`
|
||||
Store string `yaml:"store" env:"OC_CACHE_STORE" desc:"The type of the cache store. Supported values are: 'memory', 'redis-sentinel', 'nats-js-kv', 'noop'. See the text description for details." introductionVersion:"1.0.0"`
|
||||
Nodes []string `yaml:"nodes" env:"OC_CACHE_STORE_NODES" desc:"A comma separated list of nodes to access the configured store. This has no effect when 'memory' store is configured. Note that the behaviour how nodes are used is dependent on the library of the configured store." introductionVersion:"1.0.0"`
|
||||
Database string `yaml:"database" env:"OC_CACHE_STORE_DATABASE" desc:"The database name the configured store should use." introductionVersion:"1.0.0"`
|
||||
Table string `yaml:"table" env:"OC_CACHE_STORE_TABLE" desc:"The database table the store should use." introductionVersion:"1.0.0"`
|
||||
TTL time.Duration `yaml:"ttl" env:"OC_CACHE_TTL" desc:"Time to live for events in the store. The duration can be set as number followed by a unit identifier like s, m or h." introductionVersion:"1.0.0"`
|
||||
DisablePersistence bool `yaml:"disable_persistence" env:"OC_CACHE_DISABLE_PERSISTENCE" desc:"Disables persistence of the cache. Only applies when store type 'nats-js-kv' is configured. Defaults to false." introductionVersion:"1.0.0"`
|
||||
AuthUsername string `yaml:"auth_username" env:"OC_CACHE_AUTH_USERNAME" desc:"The username to use for authentication. Only applies when store type 'nats-js-kv' is configured." introductionVersion:"1.0.0"`
|
||||
AuthPassword string `yaml:"auth_password" env:"OC_CACHE_AUTH_PASSWORD" desc:"The password to use for authentication. Only applies when store type 'nats-js-kv' is configured." introductionVersion:"1.0.0"`
|
||||
EnableTLS bool `yaml:"enable_tls" env:"OC_CACHE_ENABLE_TLS" desc:"Enable TLS for the connection to file metadata cache." introductionVersion:"7.3.0"`
|
||||
TLSInsecure bool `yaml:"tls_insecure" env:"OC_INSECURE;OC_CACHE_TLS_INSECURE" desc:"Whether to verify the server TLS certificates." introductionVersion:"7.3.0"`
|
||||
TLSRootCACertificate string `yaml:"tls_root_ca_certificate" env:"OC_CACHE_TLS_ROOT_CA_CERTIFICATE" desc:"The root CA certificate used to validate the server's TLS certificate. If provided OC_CACHE_TLS_INSECURE will be seen as false." introductionVersion:"7.3.0"`
|
||||
}
|
||||
|
||||
// Commons holds configuration that are common to all extensions. Each extension can then decide whether
|
||||
|
||||
@@ -34,7 +34,7 @@ var (
|
||||
// LatestTag is the latest released version plus the dev meta version.
|
||||
// Will be overwritten by the release pipeline
|
||||
// Needs a manual change for every tagged release
|
||||
LatestTag = "7.2.0-rc.1+dev"
|
||||
LatestTag = "7.5.0+dev"
|
||||
|
||||
// Date indicates the build date.
|
||||
// This has been removed, it looks like you can only replace static strings with recent go versions
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package filepathx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// JailJoin joins any number of path elements into a single path,
|
||||
@@ -10,3 +12,27 @@ import (
|
||||
func JailJoin(jail string, elem ...string) string {
|
||||
return filepath.Join(jail, filepath.Join(append([]string{"/"}, elem...)...))
|
||||
}
|
||||
|
||||
// Determines whether the file or directory 'child' is same as or underneath the directory 'parent'.
|
||||
//
|
||||
// Note that 'parent' is expected to be a directory.
|
||||
func IsSameOrContainedBy(parent string, child string) (bool, error) {
|
||||
absParent, err := filepath.Abs(parent)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to make parent directory absolute: %q: %w", parent, err)
|
||||
}
|
||||
|
||||
absChild, err := filepath.Abs(child)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to make child file/directory absolute: %q: %w", child, err)
|
||||
}
|
||||
|
||||
rel, err := filepath.Rel(absParent, absChild)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to determine the relative path between the parent directory %q and the child file/directory: %q: %w", absParent, absChild, err)
|
||||
}
|
||||
if rel == ".." || strings.HasPrefix(rel, ".."+string(filepath.Separator)) {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
@@ -1,9 +1,12 @@
|
||||
package filepathx_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/opencloud-eu/opencloud/pkg/x/path/filepathx"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestJailJoin(t *testing.T) {
|
||||
@@ -61,3 +64,23 @@ func TestJailJoin(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsSameOrContainedBy(t *testing.T) {
|
||||
for _, tt := range []struct {
|
||||
parent string
|
||||
child string
|
||||
expected bool
|
||||
}{
|
||||
{"foo", "foo", true},
|
||||
{"/foo", "/foo", true},
|
||||
{"foo", "foo/bar", true},
|
||||
{"foo", "bar", false},
|
||||
} {
|
||||
t.Run(fmt.Sprintf("%s: %s vs %s", t.Name(), strings.ReplaceAll(tt.parent, "/", "."), strings.ReplaceAll(tt.child, "/", ".")), func(t *testing.T) {
|
||||
require := require.New(t)
|
||||
b, err := filepathx.IsSameOrContainedBy(tt.parent, tt.child)
|
||||
require.NoError(err)
|
||||
require.Equal(tt.expected, b)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -535,6 +535,267 @@ func (x *Photo) GetTakenDateTime() *timestamppb.Timestamp {
|
||||
return nil
|
||||
}
|
||||
|
||||
type Video struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
AudioBitsPerSample *int32 `protobuf:"varint,1,opt,name=audioBitsPerSample,proto3,oneof" json:"audioBitsPerSample,omitempty"`
|
||||
AudioChannels *int32 `protobuf:"varint,2,opt,name=audioChannels,proto3,oneof" json:"audioChannels,omitempty"`
|
||||
AudioFormat *string `protobuf:"bytes,3,opt,name=audioFormat,proto3,oneof" json:"audioFormat,omitempty"`
|
||||
AudioSamplesPerSecond *int32 `protobuf:"varint,4,opt,name=audioSamplesPerSecond,proto3,oneof" json:"audioSamplesPerSecond,omitempty"`
|
||||
Bitrate *int32 `protobuf:"varint,5,opt,name=bitrate,proto3,oneof" json:"bitrate,omitempty"`
|
||||
Duration *int64 `protobuf:"varint,6,opt,name=duration,proto3,oneof" json:"duration,omitempty"`
|
||||
FourCC *string `protobuf:"bytes,7,opt,name=fourCC,proto3,oneof" json:"fourCC,omitempty"`
|
||||
FrameRate *float64 `protobuf:"fixed64,8,opt,name=frameRate,proto3,oneof" json:"frameRate,omitempty"`
|
||||
Height *int32 `protobuf:"varint,9,opt,name=height,proto3,oneof" json:"height,omitempty"`
|
||||
Width *int32 `protobuf:"varint,10,opt,name=width,proto3,oneof" json:"width,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Video) Reset() {
|
||||
*x = Video{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_opencloud_messages_search_v0_search_proto_msgTypes[6]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *Video) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Video) ProtoMessage() {}
|
||||
|
||||
func (x *Video) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_opencloud_messages_search_v0_search_proto_msgTypes[6]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use Video.ProtoReflect.Descriptor instead.
|
||||
func (*Video) Descriptor() ([]byte, []int) {
|
||||
return file_opencloud_messages_search_v0_search_proto_rawDescGZIP(), []int{6}
|
||||
}
|
||||
|
||||
func (x *Video) GetAudioBitsPerSample() int32 {
|
||||
if x != nil && x.AudioBitsPerSample != nil {
|
||||
return *x.AudioBitsPerSample
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Video) GetAudioChannels() int32 {
|
||||
if x != nil && x.AudioChannels != nil {
|
||||
return *x.AudioChannels
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Video) GetAudioFormat() string {
|
||||
if x != nil && x.AudioFormat != nil {
|
||||
return *x.AudioFormat
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Video) GetAudioSamplesPerSecond() int32 {
|
||||
if x != nil && x.AudioSamplesPerSecond != nil {
|
||||
return *x.AudioSamplesPerSecond
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Video) GetBitrate() int32 {
|
||||
if x != nil && x.Bitrate != nil {
|
||||
return *x.Bitrate
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Video) GetDuration() int64 {
|
||||
if x != nil && x.Duration != nil {
|
||||
return *x.Duration
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Video) GetFourCC() string {
|
||||
if x != nil && x.FourCC != nil {
|
||||
return *x.FourCC
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Video) GetFrameRate() float64 {
|
||||
if x != nil && x.FrameRate != nil {
|
||||
return *x.FrameRate
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Video) GetHeight() int32 {
|
||||
if x != nil && x.Height != nil {
|
||||
return *x.Height
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Video) GetWidth() int32 {
|
||||
if x != nil && x.Width != nil {
|
||||
return *x.Width
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type MotionPhoto struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Version *int32 `protobuf:"varint,1,opt,name=version,proto3,oneof" json:"version,omitempty"`
|
||||
PresentationTimestampUs *int64 `protobuf:"varint,2,opt,name=presentationTimestampUs,proto3,oneof" json:"presentationTimestampUs,omitempty"`
|
||||
VideoSize *int64 `protobuf:"varint,3,opt,name=videoSize,proto3,oneof" json:"videoSize,omitempty"`
|
||||
}
|
||||
|
||||
func (x *MotionPhoto) Reset() {
|
||||
*x = MotionPhoto{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_opencloud_messages_search_v0_search_proto_msgTypes[7]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *MotionPhoto) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*MotionPhoto) ProtoMessage() {}
|
||||
|
||||
func (x *MotionPhoto) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_opencloud_messages_search_v0_search_proto_msgTypes[7]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use MotionPhoto.ProtoReflect.Descriptor instead.
|
||||
func (*MotionPhoto) Descriptor() ([]byte, []int) {
|
||||
return file_opencloud_messages_search_v0_search_proto_rawDescGZIP(), []int{7}
|
||||
}
|
||||
|
||||
func (x *MotionPhoto) GetVersion() int32 {
|
||||
if x != nil && x.Version != nil {
|
||||
return *x.Version
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *MotionPhoto) GetPresentationTimestampUs() int64 {
|
||||
if x != nil && x.PresentationTimestampUs != nil {
|
||||
return *x.PresentationTimestampUs
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *MotionPhoto) GetVideoSize() int64 {
|
||||
if x != nil && x.VideoSize != nil {
|
||||
return *x.VideoSize
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type LivePhoto struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
ContentId *string `protobuf:"bytes,1,opt,name=contentId,proto3,oneof" json:"contentId,omitempty"`
|
||||
StillImageTimeUs *int64 `protobuf:"varint,2,opt,name=stillImageTimeUs,proto3,oneof" json:"stillImageTimeUs,omitempty"`
|
||||
Auto *bool `protobuf:"varint,3,opt,name=auto,proto3,oneof" json:"auto,omitempty"`
|
||||
VitalityScore *float64 `protobuf:"fixed64,4,opt,name=vitalityScore,proto3,oneof" json:"vitalityScore,omitempty"`
|
||||
VitalityScoringVersion *int64 `protobuf:"varint,5,opt,name=vitalityScoringVersion,proto3,oneof" json:"vitalityScoringVersion,omitempty"`
|
||||
}
|
||||
|
||||
func (x *LivePhoto) Reset() {
|
||||
*x = LivePhoto{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_opencloud_messages_search_v0_search_proto_msgTypes[8]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *LivePhoto) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*LivePhoto) ProtoMessage() {}
|
||||
|
||||
func (x *LivePhoto) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_opencloud_messages_search_v0_search_proto_msgTypes[8]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use LivePhoto.ProtoReflect.Descriptor instead.
|
||||
func (*LivePhoto) Descriptor() ([]byte, []int) {
|
||||
return file_opencloud_messages_search_v0_search_proto_rawDescGZIP(), []int{8}
|
||||
}
|
||||
|
||||
func (x *LivePhoto) GetContentId() string {
|
||||
if x != nil && x.ContentId != nil {
|
||||
return *x.ContentId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *LivePhoto) GetStillImageTimeUs() int64 {
|
||||
if x != nil && x.StillImageTimeUs != nil {
|
||||
return *x.StillImageTimeUs
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *LivePhoto) GetAuto() bool {
|
||||
if x != nil && x.Auto != nil {
|
||||
return *x.Auto
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *LivePhoto) GetVitalityScore() float64 {
|
||||
if x != nil && x.VitalityScore != nil {
|
||||
return *x.VitalityScore
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *LivePhoto) GetVitalityScoringVersion() int64 {
|
||||
if x != nil && x.VitalityScoringVersion != nil {
|
||||
return *x.VitalityScoringVersion
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type Entity struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@@ -560,12 +821,15 @@ type Entity struct {
|
||||
Image *Image `protobuf:"bytes,18,opt,name=image,proto3" json:"image,omitempty"`
|
||||
Photo *Photo `protobuf:"bytes,19,opt,name=photo,proto3" json:"photo,omitempty"`
|
||||
Favorites []string `protobuf:"bytes,20,rep,name=favorites,proto3" json:"favorites,omitempty"`
|
||||
MotionPhoto *MotionPhoto `protobuf:"bytes,21,opt,name=motionPhoto,proto3" json:"motionPhoto,omitempty"`
|
||||
Video *Video `protobuf:"bytes,22,opt,name=video,proto3" json:"video,omitempty"`
|
||||
LivePhoto *LivePhoto `protobuf:"bytes,23,opt,name=livePhoto,proto3" json:"livePhoto,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Entity) Reset() {
|
||||
*x = Entity{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_opencloud_messages_search_v0_search_proto_msgTypes[6]
|
||||
mi := &file_opencloud_messages_search_v0_search_proto_msgTypes[9]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
@@ -578,7 +842,7 @@ func (x *Entity) String() string {
|
||||
func (*Entity) ProtoMessage() {}
|
||||
|
||||
func (x *Entity) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_opencloud_messages_search_v0_search_proto_msgTypes[6]
|
||||
mi := &file_opencloud_messages_search_v0_search_proto_msgTypes[9]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@@ -591,7 +855,7 @@ func (x *Entity) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use Entity.ProtoReflect.Descriptor instead.
|
||||
func (*Entity) Descriptor() ([]byte, []int) {
|
||||
return file_opencloud_messages_search_v0_search_proto_rawDescGZIP(), []int{6}
|
||||
return file_opencloud_messages_search_v0_search_proto_rawDescGZIP(), []int{9}
|
||||
}
|
||||
|
||||
func (x *Entity) GetRef() *Reference {
|
||||
@@ -734,6 +998,27 @@ func (x *Entity) GetFavorites() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Entity) GetMotionPhoto() *MotionPhoto {
|
||||
if x != nil {
|
||||
return x.MotionPhoto
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Entity) GetVideo() *Video {
|
||||
if x != nil {
|
||||
return x.Video
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Entity) GetLivePhoto() *LivePhoto {
|
||||
if x != nil {
|
||||
return x.LivePhoto
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Match struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@@ -748,7 +1033,7 @@ type Match struct {
|
||||
func (x *Match) Reset() {
|
||||
*x = Match{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_opencloud_messages_search_v0_search_proto_msgTypes[7]
|
||||
mi := &file_opencloud_messages_search_v0_search_proto_msgTypes[10]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
@@ -761,7 +1046,7 @@ func (x *Match) String() string {
|
||||
func (*Match) ProtoMessage() {}
|
||||
|
||||
func (x *Match) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_opencloud_messages_search_v0_search_proto_msgTypes[7]
|
||||
mi := &file_opencloud_messages_search_v0_search_proto_msgTypes[10]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@@ -774,7 +1059,7 @@ func (x *Match) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use Match.ProtoReflect.Descriptor instead.
|
||||
func (*Match) Descriptor() ([]byte, []int) {
|
||||
return file_opencloud_messages_search_v0_search_proto_rawDescGZIP(), []int{7}
|
||||
return file_opencloud_messages_search_v0_search_proto_rawDescGZIP(), []int{10}
|
||||
}
|
||||
|
||||
func (x *Match) GetEntity() *Entity {
|
||||
@@ -908,62 +1193,141 @@ var file_opencloud_messages_search_v0_search_proto_rawDesc = []byte{
|
||||
0x6c, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x69, 0x73, 0x6f, 0x42,
|
||||
0x0e, 0x0a, 0x0c, 0x5f, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42,
|
||||
0x10, 0x0a, 0x0e, 0x5f, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x44, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d,
|
||||
0x65, 0x22, 0xfa, 0x06, 0x0a, 0x06, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x39, 0x0a, 0x03,
|
||||
0x72, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x6f, 0x70, 0x65, 0x6e,
|
||||
0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x73,
|
||||
0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x76, 0x30, 0x2e, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e,
|
||||
0x63, 0x65, 0x52, 0x03, 0x72, 0x65, 0x66, 0x12, 0x38, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20,
|
||||
0x65, 0x22, 0x9b, 0x04, 0x0a, 0x05, 0x56, 0x69, 0x64, 0x65, 0x6f, 0x12, 0x33, 0x0a, 0x12, 0x61,
|
||||
0x75, 0x64, 0x69, 0x6f, 0x42, 0x69, 0x74, 0x73, 0x50, 0x65, 0x72, 0x53, 0x61, 0x6d, 0x70, 0x6c,
|
||||
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x48, 0x00, 0x52, 0x12, 0x61, 0x75, 0x64, 0x69, 0x6f,
|
||||
0x42, 0x69, 0x74, 0x73, 0x50, 0x65, 0x72, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x88, 0x01, 0x01,
|
||||
0x12, 0x29, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c,
|
||||
0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x48, 0x01, 0x52, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x6f,
|
||||
0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x88, 0x01, 0x01, 0x12, 0x25, 0x0a, 0x0b, 0x61,
|
||||
0x75, 0x64, 0x69, 0x6f, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
|
||||
0x48, 0x02, 0x52, 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x88,
|
||||
0x01, 0x01, 0x12, 0x39, 0x0a, 0x15, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x53, 0x61, 0x6d, 0x70, 0x6c,
|
||||
0x65, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28,
|
||||
0x05, 0x48, 0x03, 0x52, 0x15, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65,
|
||||
0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x88, 0x01, 0x01, 0x12, 0x1d, 0x0a,
|
||||
0x07, 0x62, 0x69, 0x74, 0x72, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x48, 0x04,
|
||||
0x52, 0x07, 0x62, 0x69, 0x74, 0x72, 0x61, 0x74, 0x65, 0x88, 0x01, 0x01, 0x12, 0x1f, 0x0a, 0x08,
|
||||
0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x48, 0x05,
|
||||
0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x1b, 0x0a,
|
||||
0x06, 0x66, 0x6f, 0x75, 0x72, 0x43, 0x43, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x06, 0x52,
|
||||
0x06, 0x66, 0x6f, 0x75, 0x72, 0x43, 0x43, 0x88, 0x01, 0x01, 0x12, 0x21, 0x0a, 0x09, 0x66, 0x72,
|
||||
0x61, 0x6d, 0x65, 0x52, 0x61, 0x74, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x01, 0x48, 0x07, 0x52,
|
||||
0x09, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x52, 0x61, 0x74, 0x65, 0x88, 0x01, 0x01, 0x12, 0x1b, 0x0a,
|
||||
0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x05, 0x48, 0x08, 0x52,
|
||||
0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x88, 0x01, 0x01, 0x12, 0x19, 0x0a, 0x05, 0x77, 0x69,
|
||||
0x64, 0x74, 0x68, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x48, 0x09, 0x52, 0x05, 0x77, 0x69, 0x64,
|
||||
0x74, 0x68, 0x88, 0x01, 0x01, 0x42, 0x15, 0x0a, 0x13, 0x5f, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x42,
|
||||
0x69, 0x74, 0x73, 0x50, 0x65, 0x72, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x42, 0x10, 0x0a, 0x0e,
|
||||
0x5f, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x42, 0x0e,
|
||||
0x0a, 0x0c, 0x5f, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x42, 0x18,
|
||||
0x0a, 0x16, 0x5f, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x50,
|
||||
0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x62, 0x69, 0x74,
|
||||
0x72, 0x61, 0x74, 0x65, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x66, 0x6f, 0x75, 0x72, 0x43, 0x43, 0x42, 0x0c, 0x0a, 0x0a,
|
||||
0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x52, 0x61, 0x74, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x68,
|
||||
0x65, 0x69, 0x67, 0x68, 0x74, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22,
|
||||
0xc4, 0x01, 0x0a, 0x0b, 0x4d, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x68, 0x6f, 0x74, 0x6f, 0x12,
|
||||
0x1d, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
|
||||
0x48, 0x00, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x3d,
|
||||
0x0a, 0x17, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69,
|
||||
0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x55, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x48,
|
||||
0x01, 0x52, 0x17, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54,
|
||||
0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x55, 0x73, 0x88, 0x01, 0x01, 0x12, 0x21, 0x0a,
|
||||
0x09, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03,
|
||||
0x48, 0x02, 0x52, 0x09, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x53, 0x69, 0x7a, 0x65, 0x88, 0x01, 0x01,
|
||||
0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x1a, 0x0a, 0x18,
|
||||
0x5f, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d,
|
||||
0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x55, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x76, 0x69, 0x64,
|
||||
0x65, 0x6f, 0x53, 0x69, 0x7a, 0x65, 0x22, 0xb9, 0x02, 0x0a, 0x09, 0x4c, 0x69, 0x76, 0x65, 0x50,
|
||||
0x68, 0x6f, 0x74, 0x6f, 0x12, 0x21, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x49,
|
||||
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x65,
|
||||
0x6e, 0x74, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x2f, 0x0a, 0x10, 0x73, 0x74, 0x69, 0x6c, 0x6c,
|
||||
0x49, 0x6d, 0x61, 0x67, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x55, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
0x03, 0x48, 0x01, 0x52, 0x10, 0x73, 0x74, 0x69, 0x6c, 0x6c, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x54,
|
||||
0x69, 0x6d, 0x65, 0x55, 0x73, 0x88, 0x01, 0x01, 0x12, 0x17, 0x0a, 0x04, 0x61, 0x75, 0x74, 0x6f,
|
||||
0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x48, 0x02, 0x52, 0x04, 0x61, 0x75, 0x74, 0x6f, 0x88, 0x01,
|
||||
0x01, 0x12, 0x29, 0x0a, 0x0d, 0x76, 0x69, 0x74, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x53, 0x63, 0x6f,
|
||||
0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x48, 0x03, 0x52, 0x0d, 0x76, 0x69, 0x74, 0x61,
|
||||
0x6c, 0x69, 0x74, 0x79, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x88, 0x01, 0x01, 0x12, 0x3b, 0x0a, 0x16,
|
||||
0x76, 0x69, 0x74, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x53, 0x63, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x56,
|
||||
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x48, 0x04, 0x52, 0x16,
|
||||
0x76, 0x69, 0x74, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x53, 0x63, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x56,
|
||||
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x63, 0x6f,
|
||||
0x6e, 0x74, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x73, 0x74, 0x69, 0x6c,
|
||||
0x6c, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x55, 0x73, 0x42, 0x07, 0x0a, 0x05,
|
||||
0x5f, 0x61, 0x75, 0x74, 0x6f, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x76, 0x69, 0x74, 0x61, 0x6c, 0x69,
|
||||
0x74, 0x79, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x42, 0x19, 0x0a, 0x17, 0x5f, 0x76, 0x69, 0x74, 0x61,
|
||||
0x6c, 0x69, 0x74, 0x79, 0x53, 0x63, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x65, 0x72, 0x73, 0x69,
|
||||
0x6f, 0x6e, 0x22, 0xc9, 0x08, 0x0a, 0x06, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x39, 0x0a,
|
||||
0x03, 0x72, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x6f, 0x70, 0x65,
|
||||
0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e,
|
||||
0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x76, 0x30, 0x2e, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65,
|
||||
0x6e, 0x63, 0x65, 0x52, 0x03, 0x72, 0x65, 0x66, 0x12, 0x38, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64,
|
||||
0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68,
|
||||
0x2e, 0x76, 0x30, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x44, 0x52, 0x02,
|
||||
0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x65, 0x74, 0x61, 0x67, 0x18, 0x04,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x65, 0x74, 0x61, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69,
|
||||
0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x48,
|
||||
0x0a, 0x12, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f,
|
||||
0x74, 0x69, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f,
|
||||
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d,
|
||||
0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x10, 0x6c, 0x61, 0x73, 0x74, 0x4d, 0x6f, 0x64, 0x69,
|
||||
0x66, 0x69, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x69, 0x6d, 0x65,
|
||||
0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x69, 0x6d,
|
||||
0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73,
|
||||
0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x65, 0x72, 0x6d,
|
||||
0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18,
|
||||
0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x64,
|
||||
0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, 0x65,
|
||||
0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x73, 0x68, 0x61, 0x72, 0x65, 0x52, 0x6f,
|
||||
0x6f, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x68,
|
||||
0x61, 0x72, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x45, 0x0a, 0x09, 0x70,
|
||||
0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28,
|
||||
0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61,
|
||||
0x67, 0x65, 0x73, 0x2e, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x76, 0x30, 0x2e, 0x52, 0x65,
|
||||
0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x44, 0x52, 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74,
|
||||
0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x09,
|
||||
0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x68, 0x69, 0x67, 0x68, 0x6c, 0x69,
|
||||
0x67, 0x68, 0x74, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x68, 0x69, 0x67, 0x68,
|
||||
0x6c, 0x69, 0x67, 0x68, 0x74, 0x73, 0x12, 0x39, 0x0a, 0x05, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x18,
|
||||
0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75,
|
||||
0x64, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x73, 0x65, 0x61, 0x72, 0x63,
|
||||
0x68, 0x2e, 0x76, 0x30, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x6f, 0x52, 0x05, 0x61, 0x75, 0x64, 0x69,
|
||||
0x6f, 0x12, 0x48, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x10, 0x20,
|
||||
0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e,
|
||||
0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e,
|
||||
0x76, 0x30, 0x2e, 0x47, 0x65, 0x6f, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65,
|
||||
0x73, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4e, 0x0a, 0x0e, 0x72,
|
||||
0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x11, 0x20,
|
||||
0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e,
|
||||
0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e,
|
||||
0x76, 0x30, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x44, 0x52, 0x02, 0x69,
|
||||
0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x65, 0x74, 0x61, 0x67, 0x18, 0x04, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x04, 0x65, 0x74, 0x61, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a,
|
||||
0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x48, 0x0a,
|
||||
0x12, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x74,
|
||||
0x69, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
|
||||
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65,
|
||||
0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x10, 0x6c, 0x61, 0x73, 0x74, 0x4d, 0x6f, 0x64, 0x69, 0x66,
|
||||
0x69, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x69, 0x6d, 0x65, 0x5f,
|
||||
0x74, 0x79, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x69, 0x6d, 0x65,
|
||||
0x54, 0x79, 0x70, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69,
|
||||
0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69,
|
||||
0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x09,
|
||||
0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65,
|
||||
0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, 0x65, 0x6c,
|
||||
0x65, 0x74, 0x65, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x73, 0x68, 0x61, 0x72, 0x65, 0x52, 0x6f, 0x6f,
|
||||
0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x68, 0x61,
|
||||
0x72, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x45, 0x0a, 0x09, 0x70, 0x61,
|
||||
0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e,
|
||||
0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
|
||||
0x65, 0x73, 0x2e, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x76, 0x30, 0x2e, 0x52, 0x65, 0x73,
|
||||
0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x44, 0x52, 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49,
|
||||
0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x09, 0x52,
|
||||
0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x68, 0x69, 0x67, 0x68, 0x6c, 0x69, 0x67,
|
||||
0x68, 0x74, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x68, 0x69, 0x67, 0x68, 0x6c,
|
||||
0x69, 0x67, 0x68, 0x74, 0x73, 0x12, 0x39, 0x0a, 0x05, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x18, 0x0f,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64,
|
||||
0x76, 0x30, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x44, 0x52, 0x0c, 0x72,
|
||||
0x65, 0x6d, 0x6f, 0x74, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x49, 0x64, 0x12, 0x39, 0x0a, 0x05, 0x69,
|
||||
0x6d, 0x61, 0x67, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6f, 0x70, 0x65,
|
||||
0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e,
|
||||
0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x76, 0x30, 0x2e, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52,
|
||||
0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x39, 0x0a, 0x05, 0x70, 0x68, 0x6f, 0x74, 0x6f, 0x18,
|
||||
0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75,
|
||||
0x64, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x73, 0x65, 0x61, 0x72, 0x63,
|
||||
0x68, 0x2e, 0x76, 0x30, 0x2e, 0x50, 0x68, 0x6f, 0x74, 0x6f, 0x52, 0x05, 0x70, 0x68, 0x6f, 0x74,
|
||||
0x6f, 0x12, 0x1c, 0x0a, 0x09, 0x66, 0x61, 0x76, 0x6f, 0x72, 0x69, 0x74, 0x65, 0x73, 0x18, 0x14,
|
||||
0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x66, 0x61, 0x76, 0x6f, 0x72, 0x69, 0x74, 0x65, 0x73, 0x12,
|
||||
0x4b, 0x0a, 0x0b, 0x6d, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x68, 0x6f, 0x74, 0x6f, 0x18, 0x15,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64,
|
||||
0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68,
|
||||
0x2e, 0x76, 0x30, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x6f, 0x52, 0x05, 0x61, 0x75, 0x64, 0x69, 0x6f,
|
||||
0x12, 0x48, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x10, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x6d,
|
||||
0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x76,
|
||||
0x30, 0x2e, 0x47, 0x65, 0x6f, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73,
|
||||
0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4e, 0x0a, 0x0e, 0x72, 0x65,
|
||||
0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x11, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x28, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x6d,
|
||||
0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x76,
|
||||
0x30, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x44, 0x52, 0x0c, 0x72, 0x65,
|
||||
0x6d, 0x6f, 0x74, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x49, 0x64, 0x12, 0x39, 0x0a, 0x05, 0x69, 0x6d,
|
||||
0x61, 0x67, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6f, 0x70, 0x65, 0x6e,
|
||||
0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x73,
|
||||
0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x76, 0x30, 0x2e, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x05,
|
||||
0x69, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x39, 0x0a, 0x05, 0x70, 0x68, 0x6f, 0x74, 0x6f, 0x18, 0x13,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64,
|
||||
0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68,
|
||||
0x2e, 0x76, 0x30, 0x2e, 0x50, 0x68, 0x6f, 0x74, 0x6f, 0x52, 0x05, 0x70, 0x68, 0x6f, 0x74, 0x6f,
|
||||
0x12, 0x1c, 0x0a, 0x09, 0x66, 0x61, 0x76, 0x6f, 0x72, 0x69, 0x74, 0x65, 0x73, 0x18, 0x14, 0x20,
|
||||
0x03, 0x28, 0x09, 0x52, 0x09, 0x66, 0x61, 0x76, 0x6f, 0x72, 0x69, 0x74, 0x65, 0x73, 0x22, 0x5b,
|
||||
0x2e, 0x76, 0x30, 0x2e, 0x4d, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x68, 0x6f, 0x74, 0x6f, 0x52,
|
||||
0x0b, 0x6d, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x68, 0x6f, 0x74, 0x6f, 0x12, 0x39, 0x0a, 0x05,
|
||||
0x76, 0x69, 0x64, 0x65, 0x6f, 0x18, 0x16, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6f, 0x70,
|
||||
0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73,
|
||||
0x2e, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x76, 0x30, 0x2e, 0x56, 0x69, 0x64, 0x65, 0x6f,
|
||||
0x52, 0x05, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x12, 0x45, 0x0a, 0x09, 0x6c, 0x69, 0x76, 0x65, 0x50,
|
||||
0x68, 0x6f, 0x74, 0x6f, 0x18, 0x17, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x6f, 0x70, 0x65,
|
||||
0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e,
|
||||
0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x76, 0x30, 0x2e, 0x4c, 0x69, 0x76, 0x65, 0x50, 0x68,
|
||||
0x6f, 0x74, 0x6f, 0x52, 0x09, 0x6c, 0x69, 0x76, 0x65, 0x50, 0x68, 0x6f, 0x74, 0x6f, 0x22, 0x5b,
|
||||
0x0a, 0x05, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x3c, 0x0a, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74,
|
||||
0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c,
|
||||
0x6f, 0x75, 0x64, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x73, 0x65, 0x61,
|
||||
@@ -990,7 +1354,7 @@ func file_opencloud_messages_search_v0_search_proto_rawDescGZIP() []byte {
|
||||
return file_opencloud_messages_search_v0_search_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_opencloud_messages_search_v0_search_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
|
||||
var file_opencloud_messages_search_v0_search_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
|
||||
var file_opencloud_messages_search_v0_search_proto_goTypes = []interface{}{
|
||||
(*ResourceID)(nil), // 0: opencloud.messages.search.v0.ResourceID
|
||||
(*Reference)(nil), // 1: opencloud.messages.search.v0.Reference
|
||||
@@ -998,28 +1362,34 @@ var file_opencloud_messages_search_v0_search_proto_goTypes = []interface{}{
|
||||
(*Image)(nil), // 3: opencloud.messages.search.v0.Image
|
||||
(*GeoCoordinates)(nil), // 4: opencloud.messages.search.v0.GeoCoordinates
|
||||
(*Photo)(nil), // 5: opencloud.messages.search.v0.Photo
|
||||
(*Entity)(nil), // 6: opencloud.messages.search.v0.Entity
|
||||
(*Match)(nil), // 7: opencloud.messages.search.v0.Match
|
||||
(*timestamppb.Timestamp)(nil), // 8: google.protobuf.Timestamp
|
||||
(*Video)(nil), // 6: opencloud.messages.search.v0.Video
|
||||
(*MotionPhoto)(nil), // 7: opencloud.messages.search.v0.MotionPhoto
|
||||
(*LivePhoto)(nil), // 8: opencloud.messages.search.v0.LivePhoto
|
||||
(*Entity)(nil), // 9: opencloud.messages.search.v0.Entity
|
||||
(*Match)(nil), // 10: opencloud.messages.search.v0.Match
|
||||
(*timestamppb.Timestamp)(nil), // 11: google.protobuf.Timestamp
|
||||
}
|
||||
var file_opencloud_messages_search_v0_search_proto_depIdxs = []int32{
|
||||
0, // 0: opencloud.messages.search.v0.Reference.resource_id:type_name -> opencloud.messages.search.v0.ResourceID
|
||||
8, // 1: opencloud.messages.search.v0.Photo.takenDateTime:type_name -> google.protobuf.Timestamp
|
||||
11, // 1: opencloud.messages.search.v0.Photo.takenDateTime:type_name -> google.protobuf.Timestamp
|
||||
1, // 2: opencloud.messages.search.v0.Entity.ref:type_name -> opencloud.messages.search.v0.Reference
|
||||
0, // 3: opencloud.messages.search.v0.Entity.id:type_name -> opencloud.messages.search.v0.ResourceID
|
||||
8, // 4: opencloud.messages.search.v0.Entity.last_modified_time:type_name -> google.protobuf.Timestamp
|
||||
11, // 4: opencloud.messages.search.v0.Entity.last_modified_time:type_name -> google.protobuf.Timestamp
|
||||
0, // 5: opencloud.messages.search.v0.Entity.parent_id:type_name -> opencloud.messages.search.v0.ResourceID
|
||||
2, // 6: opencloud.messages.search.v0.Entity.audio:type_name -> opencloud.messages.search.v0.Audio
|
||||
4, // 7: opencloud.messages.search.v0.Entity.location:type_name -> opencloud.messages.search.v0.GeoCoordinates
|
||||
0, // 8: opencloud.messages.search.v0.Entity.remote_item_id:type_name -> opencloud.messages.search.v0.ResourceID
|
||||
3, // 9: opencloud.messages.search.v0.Entity.image:type_name -> opencloud.messages.search.v0.Image
|
||||
5, // 10: opencloud.messages.search.v0.Entity.photo:type_name -> opencloud.messages.search.v0.Photo
|
||||
6, // 11: opencloud.messages.search.v0.Match.entity:type_name -> opencloud.messages.search.v0.Entity
|
||||
12, // [12:12] is the sub-list for method output_type
|
||||
12, // [12:12] is the sub-list for method input_type
|
||||
12, // [12:12] is the sub-list for extension type_name
|
||||
12, // [12:12] is the sub-list for extension extendee
|
||||
0, // [0:12] is the sub-list for field type_name
|
||||
7, // 11: opencloud.messages.search.v0.Entity.motionPhoto:type_name -> opencloud.messages.search.v0.MotionPhoto
|
||||
6, // 12: opencloud.messages.search.v0.Entity.video:type_name -> opencloud.messages.search.v0.Video
|
||||
8, // 13: opencloud.messages.search.v0.Entity.livePhoto:type_name -> opencloud.messages.search.v0.LivePhoto
|
||||
9, // 14: opencloud.messages.search.v0.Match.entity:type_name -> opencloud.messages.search.v0.Entity
|
||||
15, // [15:15] is the sub-list for method output_type
|
||||
15, // [15:15] is the sub-list for method input_type
|
||||
15, // [15:15] is the sub-list for extension type_name
|
||||
15, // [15:15] is the sub-list for extension extendee
|
||||
0, // [0:15] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_opencloud_messages_search_v0_search_proto_init() }
|
||||
@@ -1101,7 +1471,7 @@ func file_opencloud_messages_search_v0_search_proto_init() {
|
||||
}
|
||||
}
|
||||
file_opencloud_messages_search_v0_search_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*Entity); i {
|
||||
switch v := v.(*Video); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
@@ -1113,6 +1483,42 @@ func file_opencloud_messages_search_v0_search_proto_init() {
|
||||
}
|
||||
}
|
||||
file_opencloud_messages_search_v0_search_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*MotionPhoto); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_opencloud_messages_search_v0_search_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*LivePhoto); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_opencloud_messages_search_v0_search_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*Entity); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_opencloud_messages_search_v0_search_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*Match); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
@@ -1129,13 +1535,16 @@ func file_opencloud_messages_search_v0_search_proto_init() {
|
||||
file_opencloud_messages_search_v0_search_proto_msgTypes[3].OneofWrappers = []interface{}{}
|
||||
file_opencloud_messages_search_v0_search_proto_msgTypes[4].OneofWrappers = []interface{}{}
|
||||
file_opencloud_messages_search_v0_search_proto_msgTypes[5].OneofWrappers = []interface{}{}
|
||||
file_opencloud_messages_search_v0_search_proto_msgTypes[6].OneofWrappers = []interface{}{}
|
||||
file_opencloud_messages_search_v0_search_proto_msgTypes[7].OneofWrappers = []interface{}{}
|
||||
file_opencloud_messages_search_v0_search_proto_msgTypes[8].OneofWrappers = []interface{}{}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_opencloud_messages_search_v0_search_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 8,
|
||||
NumMessages: 11,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
|
||||
@@ -226,6 +226,42 @@ func (m *Photo) UnmarshalJSON(b []byte) error {
|
||||
|
||||
var _ json.Unmarshaler = (*Photo)(nil)
|
||||
|
||||
// VideoJSONMarshaler describes the default jsonpb.Marshaler used by all
|
||||
// instances of Video. This struct is safe to replace or modify but
|
||||
// should not be done so concurrently.
|
||||
var VideoJSONMarshaler = new(jsonpb.Marshaler)
|
||||
|
||||
// MarshalJSON satisfies the encoding/json Marshaler interface. This method
|
||||
// uses the more correct jsonpb package to correctly marshal the message.
|
||||
func (m *Video) MarshalJSON() ([]byte, error) {
|
||||
if m == nil {
|
||||
return json.Marshal(nil)
|
||||
}
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
|
||||
if err := VideoJSONMarshaler.Marshal(buf, m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
var _ json.Marshaler = (*Video)(nil)
|
||||
|
||||
// VideoJSONUnmarshaler describes the default jsonpb.Unmarshaler used by all
|
||||
// instances of Video. This struct is safe to replace or modify but
|
||||
// should not be done so concurrently.
|
||||
var VideoJSONUnmarshaler = new(jsonpb.Unmarshaler)
|
||||
|
||||
// UnmarshalJSON satisfies the encoding/json Unmarshaler interface. This method
|
||||
// uses the more correct jsonpb package to correctly unmarshal the message.
|
||||
func (m *Video) UnmarshalJSON(b []byte) error {
|
||||
return VideoJSONUnmarshaler.Unmarshal(bytes.NewReader(b), m)
|
||||
}
|
||||
|
||||
var _ json.Unmarshaler = (*Video)(nil)
|
||||
|
||||
// EntityJSONMarshaler describes the default jsonpb.Marshaler used by all
|
||||
// instances of Entity. This struct is safe to replace or modify but
|
||||
// should not be done so concurrently.
|
||||
|
||||
@@ -627,13 +627,13 @@ type Bundle struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` // @gotags: yaml:"id"
|
||||
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` // @gotags: yaml:"name"
|
||||
Type Bundle_Type `protobuf:"varint,3,opt,name=type,proto3,enum=opencloud.messages.settings.v0.Bundle_Type" json:"type,omitempty"` // @gotags: yaml:"type"
|
||||
Extension string `protobuf:"bytes,4,opt,name=extension,proto3" json:"extension,omitempty"` // @gotags: yaml:"extension"
|
||||
DisplayName string `protobuf:"bytes,5,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty"` // @gotags: yaml:"display_name"
|
||||
Settings []*Setting `protobuf:"bytes,6,rep,name=settings,proto3" json:"settings,omitempty"` // @gotags: yaml:"settings"
|
||||
Resource *Resource `protobuf:"bytes,7,opt,name=resource,proto3" json:"resource,omitempty"` // @gotags: yaml:"resource"
|
||||
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty" yaml:"id"` // @gotags: yaml:"id"
|
||||
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty" yaml:"name"` // @gotags: yaml:"name"
|
||||
Type Bundle_Type `protobuf:"varint,3,opt,name=type,proto3,enum=opencloud.messages.settings.v0.Bundle_Type" json:"type,omitempty" yaml:"type"` // @gotags: yaml:"type"
|
||||
Extension string `protobuf:"bytes,4,opt,name=extension,proto3" json:"extension,omitempty" yaml:"extension"` // @gotags: yaml:"extension"
|
||||
DisplayName string `protobuf:"bytes,5,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty" yaml:"display_name"` // @gotags: yaml:"display_name"
|
||||
Settings []*Setting `protobuf:"bytes,6,rep,name=settings,proto3" json:"settings,omitempty" yaml:"settings"` // @gotags: yaml:"settings"
|
||||
Resource *Resource `protobuf:"bytes,7,opt,name=resource,proto3" json:"resource,omitempty" yaml:"resource"` // @gotags: yaml:"resource"
|
||||
}
|
||||
|
||||
func (x *Bundle) Reset() {
|
||||
@@ -722,10 +722,10 @@ type Setting struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` // @gotags: yaml:"id"
|
||||
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` // @gotags: yaml:"name"
|
||||
DisplayName string `protobuf:"bytes,3,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty"` // @gotags: yaml:"display_name"
|
||||
Description string `protobuf:"bytes,4,opt,name=description,proto3" json:"description,omitempty"` // @gotags: yaml:"description"
|
||||
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty" yaml:"id"` // @gotags: yaml:"id"
|
||||
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty" yaml:"name"` // @gotags: yaml:"name"
|
||||
DisplayName string `protobuf:"bytes,3,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty" yaml:"display_name"` // @gotags: yaml:"display_name"
|
||||
Description string `protobuf:"bytes,4,opt,name=description,proto3" json:"description,omitempty" yaml:"description"` // @gotags: yaml:"description"
|
||||
// Types that are assignable to Value:
|
||||
//
|
||||
// *Setting_IntValue
|
||||
@@ -736,7 +736,7 @@ type Setting struct {
|
||||
// *Setting_PermissionValue
|
||||
// *Setting_MultiChoiceCollectionValue
|
||||
Value isSetting_Value `protobuf_oneof:"value"`
|
||||
Resource *Resource `protobuf:"bytes,11,opt,name=resource,proto3" json:"resource,omitempty"` // @gotags: yaml:"resource"
|
||||
Resource *Resource `protobuf:"bytes,11,opt,name=resource,proto3" json:"resource,omitempty" yaml:"resource"` // @gotags: yaml:"resource"
|
||||
}
|
||||
|
||||
func (x *Setting) Reset() {
|
||||
@@ -867,31 +867,31 @@ type isSetting_Value interface {
|
||||
}
|
||||
|
||||
type Setting_IntValue struct {
|
||||
IntValue *Int `protobuf:"bytes,5,opt,name=int_value,json=intValue,proto3,oneof"` // @gotags: yaml:"int_value"
|
||||
IntValue *Int `protobuf:"bytes,5,opt,name=int_value,json=intValue,proto3,oneof" yaml:"int_value"` // @gotags: yaml:"int_value"
|
||||
}
|
||||
|
||||
type Setting_StringValue struct {
|
||||
StringValue *String `protobuf:"bytes,6,opt,name=string_value,json=stringValue,proto3,oneof"` // @gotags: yaml:"string_value"
|
||||
StringValue *String `protobuf:"bytes,6,opt,name=string_value,json=stringValue,proto3,oneof" yaml:"string_value"` // @gotags: yaml:"string_value"
|
||||
}
|
||||
|
||||
type Setting_BoolValue struct {
|
||||
BoolValue *Bool `protobuf:"bytes,7,opt,name=bool_value,json=boolValue,proto3,oneof"` // @gotags: yaml:"bool_value"
|
||||
BoolValue *Bool `protobuf:"bytes,7,opt,name=bool_value,json=boolValue,proto3,oneof" yaml:"bool_value"` // @gotags: yaml:"bool_value"
|
||||
}
|
||||
|
||||
type Setting_SingleChoiceValue struct {
|
||||
SingleChoiceValue *SingleChoiceList `protobuf:"bytes,8,opt,name=single_choice_value,json=singleChoiceValue,proto3,oneof"` // @gotags: yaml:"single_choice_value"
|
||||
SingleChoiceValue *SingleChoiceList `protobuf:"bytes,8,opt,name=single_choice_value,json=singleChoiceValue,proto3,oneof" yaml:"single_choice_value"` // @gotags: yaml:"single_choice_value"
|
||||
}
|
||||
|
||||
type Setting_MultiChoiceValue struct {
|
||||
MultiChoiceValue *MultiChoiceList `protobuf:"bytes,9,opt,name=multi_choice_value,json=multiChoiceValue,proto3,oneof"` // @gotags: yaml:"multi_choice_value"
|
||||
MultiChoiceValue *MultiChoiceList `protobuf:"bytes,9,opt,name=multi_choice_value,json=multiChoiceValue,proto3,oneof" yaml:"multi_choice_value"` // @gotags: yaml:"multi_choice_value"
|
||||
}
|
||||
|
||||
type Setting_PermissionValue struct {
|
||||
PermissionValue *Permission `protobuf:"bytes,10,opt,name=permission_value,json=permissionValue,proto3,oneof"` // @gotags: yaml:"permission_value"
|
||||
PermissionValue *Permission `protobuf:"bytes,10,opt,name=permission_value,json=permissionValue,proto3,oneof" yaml:"permission_value"` // @gotags: yaml:"permission_value"
|
||||
}
|
||||
|
||||
type Setting_MultiChoiceCollectionValue struct {
|
||||
MultiChoiceCollectionValue *MultiChoiceCollection `protobuf:"bytes,12,opt,name=multi_choice_collection_value,json=multiChoiceCollectionValue,proto3,oneof"` // @gotags: yaml:"multi_choice_collection_value"
|
||||
MultiChoiceCollectionValue *MultiChoiceCollection `protobuf:"bytes,12,opt,name=multi_choice_collection_value,json=multiChoiceCollectionValue,proto3,oneof" yaml:"multi_choice_collection_value"` // @gotags: yaml:"multi_choice_collection_value"
|
||||
}
|
||||
|
||||
func (*Setting_IntValue) isSetting_Value() {}
|
||||
@@ -913,11 +913,11 @@ type Int struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Default int64 `protobuf:"varint,1,opt,name=default,proto3" json:"default,omitempty"` // @gotags: yaml:"default"
|
||||
Min int64 `protobuf:"varint,2,opt,name=min,proto3" json:"min,omitempty"` // @gotags: yaml:"min"
|
||||
Max int64 `protobuf:"varint,3,opt,name=max,proto3" json:"max,omitempty"` // @gotags: yaml:"max"
|
||||
Step int64 `protobuf:"varint,4,opt,name=step,proto3" json:"step,omitempty"` // @gotags: yaml:"step"
|
||||
Placeholder string `protobuf:"bytes,5,opt,name=placeholder,proto3" json:"placeholder,omitempty"` // @gotags: yaml:"placeholder"
|
||||
Default int64 `protobuf:"varint,1,opt,name=default,proto3" json:"default,omitempty" yaml:"default"` // @gotags: yaml:"default"
|
||||
Min int64 `protobuf:"varint,2,opt,name=min,proto3" json:"min,omitempty" yaml:"min"` // @gotags: yaml:"min"
|
||||
Max int64 `protobuf:"varint,3,opt,name=max,proto3" json:"max,omitempty" yaml:"max"` // @gotags: yaml:"max"
|
||||
Step int64 `protobuf:"varint,4,opt,name=step,proto3" json:"step,omitempty" yaml:"step"` // @gotags: yaml:"step"
|
||||
Placeholder string `protobuf:"bytes,5,opt,name=placeholder,proto3" json:"placeholder,omitempty" yaml:"placeholder"` // @gotags: yaml:"placeholder"
|
||||
}
|
||||
|
||||
func (x *Int) Reset() {
|
||||
@@ -992,11 +992,11 @@ type String struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Default string `protobuf:"bytes,1,opt,name=default,proto3" json:"default,omitempty"` // @gotags: yaml:"default"
|
||||
Required bool `protobuf:"varint,2,opt,name=required,proto3" json:"required,omitempty"` // @gotags: yaml:"required"
|
||||
MinLength int32 `protobuf:"varint,3,opt,name=min_length,json=minLength,proto3" json:"min_length,omitempty"` // @gotags: yaml:"min_length"
|
||||
MaxLength int32 `protobuf:"varint,4,opt,name=max_length,json=maxLength,proto3" json:"max_length,omitempty"` // @gotags: yaml:"max_length"
|
||||
Placeholder string `protobuf:"bytes,5,opt,name=placeholder,proto3" json:"placeholder,omitempty"` // @gotags: yaml:"placeholder"
|
||||
Default string `protobuf:"bytes,1,opt,name=default,proto3" json:"default,omitempty" yaml:"default"` // @gotags: yaml:"default"
|
||||
Required bool `protobuf:"varint,2,opt,name=required,proto3" json:"required,omitempty" yaml:"required"` // @gotags: yaml:"required"
|
||||
MinLength int32 `protobuf:"varint,3,opt,name=min_length,json=minLength,proto3" json:"min_length,omitempty" yaml:"min_length"` // @gotags: yaml:"min_length"
|
||||
MaxLength int32 `protobuf:"varint,4,opt,name=max_length,json=maxLength,proto3" json:"max_length,omitempty" yaml:"max_length"` // @gotags: yaml:"max_length"
|
||||
Placeholder string `protobuf:"bytes,5,opt,name=placeholder,proto3" json:"placeholder,omitempty" yaml:"placeholder"` // @gotags: yaml:"placeholder"
|
||||
}
|
||||
|
||||
func (x *String) Reset() {
|
||||
@@ -1071,8 +1071,8 @@ type Bool struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Default bool `protobuf:"varint,1,opt,name=default,proto3" json:"default,omitempty"` // @gotags: yaml:"default"
|
||||
Label string `protobuf:"bytes,2,opt,name=label,proto3" json:"label,omitempty"` // @gotags: yaml:"label"
|
||||
Default bool `protobuf:"varint,1,opt,name=default,proto3" json:"default,omitempty" yaml:"default"` // @gotags: yaml:"default"
|
||||
Label string `protobuf:"bytes,2,opt,name=label,proto3" json:"label,omitempty" yaml:"label"` // @gotags: yaml:"label"
|
||||
}
|
||||
|
||||
func (x *Bool) Reset() {
|
||||
@@ -1126,7 +1126,7 @@ type SingleChoiceList struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Options []*ListOption `protobuf:"bytes,1,rep,name=options,proto3" json:"options,omitempty"` // @gotags: yaml:"options"
|
||||
Options []*ListOption `protobuf:"bytes,1,rep,name=options,proto3" json:"options,omitempty" yaml:"options"` // @gotags: yaml:"options"
|
||||
}
|
||||
|
||||
func (x *SingleChoiceList) Reset() {
|
||||
@@ -1173,7 +1173,7 @@ type MultiChoiceList struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Options []*ListOption `protobuf:"bytes,1,rep,name=options,proto3" json:"options,omitempty"` // @gotags: yaml:"options"
|
||||
Options []*ListOption `protobuf:"bytes,1,rep,name=options,proto3" json:"options,omitempty" yaml:"options"` // @gotags: yaml:"options"
|
||||
}
|
||||
|
||||
func (x *MultiChoiceList) Reset() {
|
||||
@@ -1220,9 +1220,9 @@ type ListOption struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Value *ListOptionValue `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` // @gotags: yaml:"value"
|
||||
Default bool `protobuf:"varint,2,opt,name=default,proto3" json:"default,omitempty"` // @gotags: yaml:"default"
|
||||
DisplayValue string `protobuf:"bytes,3,opt,name=display_value,json=displayValue,proto3" json:"display_value,omitempty"` // @gotags: yaml:"display_value"
|
||||
Value *ListOptionValue `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty" yaml:"value"` // @gotags: yaml:"value"
|
||||
Default bool `protobuf:"varint,2,opt,name=default,proto3" json:"default,omitempty" yaml:"default"` // @gotags: yaml:"default"
|
||||
DisplayValue string `protobuf:"bytes,3,opt,name=display_value,json=displayValue,proto3" json:"display_value,omitempty" yaml:"display_value"` // @gotags: yaml:"display_value"
|
||||
}
|
||||
|
||||
func (x *ListOption) Reset() {
|
||||
@@ -1283,7 +1283,7 @@ type MultiChoiceCollection struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Options []*MultiChoiceCollectionOption `protobuf:"bytes,1,rep,name=options,proto3" json:"options,omitempty"` // @gotags: yaml:"options"
|
||||
Options []*MultiChoiceCollectionOption `protobuf:"bytes,1,rep,name=options,proto3" json:"options,omitempty" yaml:"options"` // @gotags: yaml:"options"
|
||||
}
|
||||
|
||||
func (x *MultiChoiceCollection) Reset() {
|
||||
@@ -1330,10 +1330,10 @@ type MultiChoiceCollectionOption struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Value *MultiChoiceCollectionOptionValue `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` // @gotags: yaml:"value"
|
||||
Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"` // @gotags: yaml:"key"
|
||||
Attribute string `protobuf:"bytes,3,opt,name=attribute,proto3" json:"attribute,omitempty"` // @gotags: yaml:"attribute"
|
||||
DisplayValue string `protobuf:"bytes,4,opt,name=display_value,json=displayValue,proto3" json:"display_value,omitempty"` // @gotags: yaml:"display_value"
|
||||
Value *MultiChoiceCollectionOptionValue `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty" yaml:"value"` // @gotags: yaml:"value"
|
||||
Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty" yaml:"key"` // @gotags: yaml:"key"
|
||||
Attribute string `protobuf:"bytes,3,opt,name=attribute,proto3" json:"attribute,omitempty" yaml:"attribute"` // @gotags: yaml:"attribute"
|
||||
DisplayValue string `protobuf:"bytes,4,opt,name=display_value,json=displayValue,proto3" json:"display_value,omitempty" yaml:"display_value"` // @gotags: yaml:"display_value"
|
||||
}
|
||||
|
||||
func (x *MultiChoiceCollectionOption) Reset() {
|
||||
@@ -1474,15 +1474,15 @@ type isMultiChoiceCollectionOptionValue_Option interface {
|
||||
}
|
||||
|
||||
type MultiChoiceCollectionOptionValue_IntValue struct {
|
||||
IntValue *Int `protobuf:"bytes,1,opt,name=int_value,json=intValue,proto3,oneof"` // @gotags: yaml:"int_value"
|
||||
IntValue *Int `protobuf:"bytes,1,opt,name=int_value,json=intValue,proto3,oneof" yaml:"int_value"` // @gotags: yaml:"int_value"
|
||||
}
|
||||
|
||||
type MultiChoiceCollectionOptionValue_StringValue struct {
|
||||
StringValue *String `protobuf:"bytes,2,opt,name=string_value,json=stringValue,proto3,oneof"` // @gotags: yaml:"string_value"
|
||||
StringValue *String `protobuf:"bytes,2,opt,name=string_value,json=stringValue,proto3,oneof" yaml:"string_value"` // @gotags: yaml:"string_value"
|
||||
}
|
||||
|
||||
type MultiChoiceCollectionOptionValue_BoolValue struct {
|
||||
BoolValue *Bool `protobuf:"bytes,3,opt,name=bool_value,json=boolValue,proto3,oneof"` // @gotags: yaml:"bool_value"
|
||||
BoolValue *Bool `protobuf:"bytes,3,opt,name=bool_value,json=boolValue,proto3,oneof" yaml:"bool_value"` // @gotags: yaml:"bool_value"
|
||||
}
|
||||
|
||||
func (*MultiChoiceCollectionOptionValue_IntValue) isMultiChoiceCollectionOptionValue_Option() {}
|
||||
@@ -1496,8 +1496,8 @@ type Permission struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Operation Permission_Operation `protobuf:"varint,1,opt,name=operation,proto3,enum=opencloud.messages.settings.v0.Permission_Operation" json:"operation,omitempty"` // @gotags: yaml:"operation"
|
||||
Constraint Permission_Constraint `protobuf:"varint,2,opt,name=constraint,proto3,enum=opencloud.messages.settings.v0.Permission_Constraint" json:"constraint,omitempty"` // @gotags: yaml:"constraint"
|
||||
Operation Permission_Operation `protobuf:"varint,1,opt,name=operation,proto3,enum=opencloud.messages.settings.v0.Permission_Operation" json:"operation,omitempty" yaml:"operation"` // @gotags: yaml:"operation"
|
||||
Constraint Permission_Constraint `protobuf:"varint,2,opt,name=constraint,proto3,enum=opencloud.messages.settings.v0.Permission_Constraint" json:"constraint,omitempty" yaml:"constraint"` // @gotags: yaml:"constraint"
|
||||
}
|
||||
|
||||
func (x *Permission) Reset() {
|
||||
@@ -1552,12 +1552,12 @@ type Value struct {
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// id is the id of the Value. It is generated on saving it.
|
||||
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` // @gotags: yaml:"id"
|
||||
BundleId string `protobuf:"bytes,2,opt,name=bundle_id,json=bundleId,proto3" json:"bundle_id,omitempty"` // @gotags: yaml:"bundle_id"
|
||||
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty" yaml:"id"` // @gotags: yaml:"id"
|
||||
BundleId string `protobuf:"bytes,2,opt,name=bundle_id,json=bundleId,proto3" json:"bundle_id,omitempty" yaml:"bundle_id"` // @gotags: yaml:"bundle_id"
|
||||
// setting_id is the id of the setting from within its bundle.
|
||||
SettingId string `protobuf:"bytes,3,opt,name=setting_id,json=settingId,proto3" json:"setting_id,omitempty"` // @gotags: yaml:"setting_id"
|
||||
AccountUuid string `protobuf:"bytes,4,opt,name=account_uuid,json=accountUuid,proto3" json:"account_uuid,omitempty"` // @gotags: yaml:"account_uuid"
|
||||
Resource *Resource `protobuf:"bytes,5,opt,name=resource,proto3" json:"resource,omitempty"` // @gotags: yaml:"resource"
|
||||
SettingId string `protobuf:"bytes,3,opt,name=setting_id,json=settingId,proto3" json:"setting_id,omitempty" yaml:"setting_id"` // @gotags: yaml:"setting_id"
|
||||
AccountUuid string `protobuf:"bytes,4,opt,name=account_uuid,json=accountUuid,proto3" json:"account_uuid,omitempty" yaml:"account_uuid"` // @gotags: yaml:"account_uuid"
|
||||
Resource *Resource `protobuf:"bytes,5,opt,name=resource,proto3" json:"resource,omitempty" yaml:"resource"` // @gotags: yaml:"resource"
|
||||
// Types that are assignable to Value:
|
||||
//
|
||||
// *Value_BoolValue
|
||||
@@ -1682,23 +1682,23 @@ type isValue_Value interface {
|
||||
}
|
||||
|
||||
type Value_BoolValue struct {
|
||||
BoolValue bool `protobuf:"varint,6,opt,name=bool_value,json=boolValue,proto3,oneof"` // @gotags: yaml:"bool_value"
|
||||
BoolValue bool `protobuf:"varint,6,opt,name=bool_value,json=boolValue,proto3,oneof" yaml:"bool_value"` // @gotags: yaml:"bool_value"
|
||||
}
|
||||
|
||||
type Value_IntValue struct {
|
||||
IntValue int64 `protobuf:"varint,7,opt,name=int_value,json=intValue,proto3,oneof"` // @gotags: yaml:"int_value"
|
||||
IntValue int64 `protobuf:"varint,7,opt,name=int_value,json=intValue,proto3,oneof" yaml:"int_value"` // @gotags: yaml:"int_value"
|
||||
}
|
||||
|
||||
type Value_StringValue struct {
|
||||
StringValue string `protobuf:"bytes,8,opt,name=string_value,json=stringValue,proto3,oneof"` // @gotags: yaml:"string_value"
|
||||
StringValue string `protobuf:"bytes,8,opt,name=string_value,json=stringValue,proto3,oneof" yaml:"string_value"` // @gotags: yaml:"string_value"
|
||||
}
|
||||
|
||||
type Value_ListValue struct {
|
||||
ListValue *ListValue `protobuf:"bytes,9,opt,name=list_value,json=listValue,proto3,oneof"` // @gotags: yaml:"list_value"
|
||||
ListValue *ListValue `protobuf:"bytes,9,opt,name=list_value,json=listValue,proto3,oneof" yaml:"list_value"` // @gotags: yaml:"list_value"
|
||||
}
|
||||
|
||||
type Value_CollectionValue struct {
|
||||
CollectionValue *CollectionValue `protobuf:"bytes,10,opt,name=collection_value,json=collectionValue,proto3,oneof"` // @gotags: yaml:"collection_value"
|
||||
CollectionValue *CollectionValue `protobuf:"bytes,10,opt,name=collection_value,json=collectionValue,proto3,oneof" yaml:"collection_value"` // @gotags: yaml:"collection_value"
|
||||
}
|
||||
|
||||
func (*Value_BoolValue) isValue_Value() {}
|
||||
@@ -1716,7 +1716,7 @@ type ListValue struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Values []*ListOptionValue `protobuf:"bytes,1,rep,name=values,proto3" json:"values,omitempty"` // @gotags: yaml:"values"
|
||||
Values []*ListOptionValue `protobuf:"bytes,1,rep,name=values,proto3" json:"values,omitempty" yaml:"values"` // @gotags: yaml:"values"
|
||||
}
|
||||
|
||||
func (x *ListValue) Reset() {
|
||||
@@ -1836,15 +1836,15 @@ type isListOptionValue_Option interface {
|
||||
}
|
||||
|
||||
type ListOptionValue_StringValue struct {
|
||||
StringValue string `protobuf:"bytes,1,opt,name=string_value,json=stringValue,proto3,oneof"` // @gotags: yaml:"string_value"
|
||||
StringValue string `protobuf:"bytes,1,opt,name=string_value,json=stringValue,proto3,oneof" yaml:"string_value"` // @gotags: yaml:"string_value"
|
||||
}
|
||||
|
||||
type ListOptionValue_IntValue struct {
|
||||
IntValue int64 `protobuf:"varint,2,opt,name=int_value,json=intValue,proto3,oneof"` // @gotags: yaml:"int_value"
|
||||
IntValue int64 `protobuf:"varint,2,opt,name=int_value,json=intValue,proto3,oneof" yaml:"int_value"` // @gotags: yaml:"int_value"
|
||||
}
|
||||
|
||||
type ListOptionValue_BoolValue struct {
|
||||
BoolValue bool `protobuf:"varint,3,opt,name=bool_value,json=boolValue,proto3,oneof"` // @gotags: yaml:"bool_value"
|
||||
BoolValue bool `protobuf:"varint,3,opt,name=bool_value,json=boolValue,proto3,oneof" yaml:"bool_value"` // @gotags: yaml:"bool_value"
|
||||
}
|
||||
|
||||
func (*ListOptionValue_StringValue) isListOptionValue_Option() {}
|
||||
@@ -1858,7 +1858,7 @@ type CollectionValue struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Values []*CollectionOption `protobuf:"bytes,1,rep,name=values,proto3" json:"values,omitempty"` // @gotags: yaml:"values"
|
||||
Values []*CollectionOption `protobuf:"bytes,1,rep,name=values,proto3" json:"values,omitempty" yaml:"values"` // @gotags: yaml:"values"
|
||||
}
|
||||
|
||||
func (x *CollectionValue) Reset() {
|
||||
@@ -1906,7 +1906,7 @@ type CollectionOption struct {
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// required
|
||||
Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` // @gotags: yaml:"key"
|
||||
Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty" yaml:"key"` // @gotags: yaml:"key"
|
||||
// Types that are assignable to Option:
|
||||
//
|
||||
// *CollectionOption_IntValue
|
||||
@@ -1987,15 +1987,15 @@ type isCollectionOption_Option interface {
|
||||
}
|
||||
|
||||
type CollectionOption_IntValue struct {
|
||||
IntValue int64 `protobuf:"varint,2,opt,name=int_value,json=intValue,proto3,oneof"` // @gotags: yaml:"int_value"
|
||||
IntValue int64 `protobuf:"varint,2,opt,name=int_value,json=intValue,proto3,oneof" yaml:"int_value"` // @gotags: yaml:"int_value"
|
||||
}
|
||||
|
||||
type CollectionOption_StringValue struct {
|
||||
StringValue string `protobuf:"bytes,3,opt,name=string_value,json=stringValue,proto3,oneof"` // @gotags: yaml:"string_value"
|
||||
StringValue string `protobuf:"bytes,3,opt,name=string_value,json=stringValue,proto3,oneof" yaml:"string_value"` // @gotags: yaml:"string_value"
|
||||
}
|
||||
|
||||
type CollectionOption_BoolValue struct {
|
||||
BoolValue bool `protobuf:"varint,4,opt,name=bool_value,json=boolValue,proto3,oneof"` // @gotags: yaml:"bool_value"
|
||||
BoolValue bool `protobuf:"varint,4,opt,name=bool_value,json=boolValue,proto3,oneof" yaml:"bool_value"` // @gotags: yaml:"bool_value"
|
||||
}
|
||||
|
||||
func (*CollectionOption_IntValue) isCollectionOption_Option() {}
|
||||
|
||||
@@ -1,326 +0,0 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc (unknown)
|
||||
// source: opencloud/messages/thumbnails/v0/thumbnails.proto
|
||||
|
||||
package v0
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// The file types to which the thumbnail can be encoded to.
|
||||
type ThumbnailType int32
|
||||
|
||||
const (
|
||||
ThumbnailType_PNG ThumbnailType = 0 // Represents PNG type
|
||||
ThumbnailType_JPG ThumbnailType = 1 // Represents JPG type
|
||||
ThumbnailType_GIF ThumbnailType = 2 // Represents GIF type
|
||||
)
|
||||
|
||||
// Enum value maps for ThumbnailType.
|
||||
var (
|
||||
ThumbnailType_name = map[int32]string{
|
||||
0: "PNG",
|
||||
1: "JPG",
|
||||
2: "GIF",
|
||||
}
|
||||
ThumbnailType_value = map[string]int32{
|
||||
"PNG": 0,
|
||||
"JPG": 1,
|
||||
"GIF": 2,
|
||||
}
|
||||
)
|
||||
|
||||
func (x ThumbnailType) Enum() *ThumbnailType {
|
||||
p := new(ThumbnailType)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
|
||||
func (x ThumbnailType) String() string {
|
||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||
}
|
||||
|
||||
func (ThumbnailType) Descriptor() protoreflect.EnumDescriptor {
|
||||
return file_opencloud_messages_thumbnails_v0_thumbnails_proto_enumTypes[0].Descriptor()
|
||||
}
|
||||
|
||||
func (ThumbnailType) Type() protoreflect.EnumType {
|
||||
return &file_opencloud_messages_thumbnails_v0_thumbnails_proto_enumTypes[0]
|
||||
}
|
||||
|
||||
func (x ThumbnailType) Number() protoreflect.EnumNumber {
|
||||
return protoreflect.EnumNumber(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ThumbnailType.Descriptor instead.
|
||||
func (ThumbnailType) EnumDescriptor() ([]byte, []int) {
|
||||
return file_opencloud_messages_thumbnails_v0_thumbnails_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
type WebdavSource struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// REQUIRED.
|
||||
Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"`
|
||||
// REQUIRED.
|
||||
IsPublicLink bool `protobuf:"varint,2,opt,name=is_public_link,json=isPublicLink,proto3" json:"is_public_link,omitempty"`
|
||||
// OPTIONAL.
|
||||
WebdavAuthorization string `protobuf:"bytes,3,opt,name=webdav_authorization,json=webdavAuthorization,proto3" json:"webdav_authorization,omitempty"`
|
||||
// OPTIONAL.
|
||||
RevaAuthorization string `protobuf:"bytes,4,opt,name=reva_authorization,json=revaAuthorization,proto3" json:"reva_authorization,omitempty"`
|
||||
// OPTIONAL.
|
||||
PublicLinkToken string `protobuf:"bytes,5,opt,name=public_link_token,json=publicLinkToken,proto3" json:"public_link_token,omitempty"`
|
||||
}
|
||||
|
||||
func (x *WebdavSource) Reset() {
|
||||
*x = WebdavSource{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_opencloud_messages_thumbnails_v0_thumbnails_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *WebdavSource) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*WebdavSource) ProtoMessage() {}
|
||||
|
||||
func (x *WebdavSource) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_opencloud_messages_thumbnails_v0_thumbnails_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use WebdavSource.ProtoReflect.Descriptor instead.
|
||||
func (*WebdavSource) Descriptor() ([]byte, []int) {
|
||||
return file_opencloud_messages_thumbnails_v0_thumbnails_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *WebdavSource) GetUrl() string {
|
||||
if x != nil {
|
||||
return x.Url
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *WebdavSource) GetIsPublicLink() bool {
|
||||
if x != nil {
|
||||
return x.IsPublicLink
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *WebdavSource) GetWebdavAuthorization() string {
|
||||
if x != nil {
|
||||
return x.WebdavAuthorization
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *WebdavSource) GetRevaAuthorization() string {
|
||||
if x != nil {
|
||||
return x.RevaAuthorization
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *WebdavSource) GetPublicLinkToken() string {
|
||||
if x != nil {
|
||||
return x.PublicLinkToken
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type CS3Source struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"`
|
||||
Authorization string `protobuf:"bytes,2,opt,name=authorization,proto3" json:"authorization,omitempty"`
|
||||
}
|
||||
|
||||
func (x *CS3Source) Reset() {
|
||||
*x = CS3Source{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_opencloud_messages_thumbnails_v0_thumbnails_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *CS3Source) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*CS3Source) ProtoMessage() {}
|
||||
|
||||
func (x *CS3Source) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_opencloud_messages_thumbnails_v0_thumbnails_proto_msgTypes[1]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use CS3Source.ProtoReflect.Descriptor instead.
|
||||
func (*CS3Source) Descriptor() ([]byte, []int) {
|
||||
return file_opencloud_messages_thumbnails_v0_thumbnails_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *CS3Source) GetPath() string {
|
||||
if x != nil {
|
||||
return x.Path
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *CS3Source) GetAuthorization() string {
|
||||
if x != nil {
|
||||
return x.Authorization
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var File_opencloud_messages_thumbnails_v0_thumbnails_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_opencloud_messages_thumbnails_v0_thumbnails_proto_rawDesc = []byte{
|
||||
0x0a, 0x31, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2f, 0x6d, 0x65, 0x73, 0x73,
|
||||
0x61, 0x67, 0x65, 0x73, 0x2f, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x6e, 0x61, 0x69, 0x6c, 0x73, 0x2f,
|
||||
0x76, 0x30, 0x2f, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x6e, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x12, 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x6d,
|
||||
0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x6e, 0x61, 0x69,
|
||||
0x6c, 0x73, 0x2e, 0x76, 0x30, 0x22, 0xd4, 0x01, 0x0a, 0x0c, 0x57, 0x65, 0x62, 0x64, 0x61, 0x76,
|
||||
0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x24, 0x0a, 0x0e, 0x69, 0x73, 0x5f, 0x70,
|
||||
0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08,
|
||||
0x52, 0x0c, 0x69, 0x73, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x31,
|
||||
0x0a, 0x14, 0x77, 0x65, 0x62, 0x64, 0x61, 0x76, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69,
|
||||
0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x77, 0x65,
|
||||
0x62, 0x64, 0x61, 0x76, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x12, 0x2d, 0x0a, 0x12, 0x72, 0x65, 0x76, 0x61, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72,
|
||||
0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x72,
|
||||
0x65, 0x76, 0x61, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x12, 0x2a, 0x0a, 0x11, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6c, 0x69, 0x6e, 0x6b, 0x5f,
|
||||
0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x70, 0x75, 0x62,
|
||||
0x6c, 0x69, 0x63, 0x4c, 0x69, 0x6e, 0x6b, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x45, 0x0a, 0x09,
|
||||
0x43, 0x53, 0x33, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74,
|
||||
0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x24, 0x0a,
|
||||
0x0d, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x2a, 0x2a, 0x0a, 0x0d, 0x54, 0x68, 0x75, 0x6d, 0x62, 0x6e, 0x61, 0x69, 0x6c,
|
||||
0x54, 0x79, 0x70, 0x65, 0x12, 0x07, 0x0a, 0x03, 0x50, 0x4e, 0x47, 0x10, 0x00, 0x12, 0x07, 0x0a,
|
||||
0x03, 0x4a, 0x50, 0x47, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x47, 0x49, 0x46, 0x10, 0x02, 0x42,
|
||||
0x51, 0x5a, 0x4f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70,
|
||||
0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2d, 0x65, 0x75, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63,
|
||||
0x6c, 0x6f, 0x75, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x65,
|
||||
0x6e, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2f, 0x6d, 0x65, 0x73, 0x73,
|
||||
0x61, 0x67, 0x65, 0x73, 0x2f, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x6e, 0x61, 0x69, 0x6c, 0x73, 0x2f,
|
||||
0x76, 0x30, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_opencloud_messages_thumbnails_v0_thumbnails_proto_rawDescOnce sync.Once
|
||||
file_opencloud_messages_thumbnails_v0_thumbnails_proto_rawDescData = file_opencloud_messages_thumbnails_v0_thumbnails_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_opencloud_messages_thumbnails_v0_thumbnails_proto_rawDescGZIP() []byte {
|
||||
file_opencloud_messages_thumbnails_v0_thumbnails_proto_rawDescOnce.Do(func() {
|
||||
file_opencloud_messages_thumbnails_v0_thumbnails_proto_rawDescData = protoimpl.X.CompressGZIP(file_opencloud_messages_thumbnails_v0_thumbnails_proto_rawDescData)
|
||||
})
|
||||
return file_opencloud_messages_thumbnails_v0_thumbnails_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_opencloud_messages_thumbnails_v0_thumbnails_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
||||
var file_opencloud_messages_thumbnails_v0_thumbnails_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
||||
var file_opencloud_messages_thumbnails_v0_thumbnails_proto_goTypes = []interface{}{
|
||||
(ThumbnailType)(0), // 0: opencloud.messages.thumbnails.v0.ThumbnailType
|
||||
(*WebdavSource)(nil), // 1: opencloud.messages.thumbnails.v0.WebdavSource
|
||||
(*CS3Source)(nil), // 2: opencloud.messages.thumbnails.v0.CS3Source
|
||||
}
|
||||
var file_opencloud_messages_thumbnails_v0_thumbnails_proto_depIdxs = []int32{
|
||||
0, // [0:0] is the sub-list for method output_type
|
||||
0, // [0:0] is the sub-list for method input_type
|
||||
0, // [0:0] is the sub-list for extension type_name
|
||||
0, // [0:0] is the sub-list for extension extendee
|
||||
0, // [0:0] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_opencloud_messages_thumbnails_v0_thumbnails_proto_init() }
|
||||
func file_opencloud_messages_thumbnails_v0_thumbnails_proto_init() {
|
||||
if File_opencloud_messages_thumbnails_v0_thumbnails_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_opencloud_messages_thumbnails_v0_thumbnails_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*WebdavSource); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_opencloud_messages_thumbnails_v0_thumbnails_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*CS3Source); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_opencloud_messages_thumbnails_v0_thumbnails_proto_rawDesc,
|
||||
NumEnums: 1,
|
||||
NumMessages: 2,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_opencloud_messages_thumbnails_v0_thumbnails_proto_goTypes,
|
||||
DependencyIndexes: file_opencloud_messages_thumbnails_v0_thumbnails_proto_depIdxs,
|
||||
EnumInfos: file_opencloud_messages_thumbnails_v0_thumbnails_proto_enumTypes,
|
||||
MessageInfos: file_opencloud_messages_thumbnails_v0_thumbnails_proto_msgTypes,
|
||||
}.Build()
|
||||
File_opencloud_messages_thumbnails_v0_thumbnails_proto = out.File
|
||||
file_opencloud_messages_thumbnails_v0_thumbnails_proto_rawDesc = nil
|
||||
file_opencloud_messages_thumbnails_v0_thumbnails_proto_goTypes = nil
|
||||
file_opencloud_messages_thumbnails_v0_thumbnails_proto_depIdxs = nil
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
// Code generated by protoc-gen-micro. DO NOT EDIT.
|
||||
// source: opencloud/messages/thumbnails/v0/thumbnails.proto
|
||||
|
||||
package v0
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "google.golang.org/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
@@ -1,43 +0,0 @@
|
||||
{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"title": "opencloud/messages/thumbnails/v0/thumbnails.proto",
|
||||
"version": "version not set"
|
||||
},
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"paths": {},
|
||||
"definitions": {
|
||||
"protobufAny": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"@type": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": {}
|
||||
},
|
||||
"rpcStatus": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"code": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"details": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/protobufAny"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,7 @@ func (_m *SearchProviderService) EXPECT() *SearchProviderService_Expecter {
|
||||
}
|
||||
|
||||
// IndexSpace provides a mock function for the type SearchProviderService
|
||||
func (_mock *SearchProviderService) IndexSpace(ctx context.Context, in *v0.IndexSpaceRequest, opts ...client.CallOption) (*v0.IndexSpaceResponse, error) {
|
||||
func (_mock *SearchProviderService) IndexSpace(ctx context.Context, in *v0.IndexSpaceRequest, opts ...client.CallOption) (v0.SearchProvider_IndexSpaceService, error) {
|
||||
var tmpRet mock.Arguments
|
||||
if len(opts) > 0 {
|
||||
tmpRet = _mock.Called(ctx, in, opts)
|
||||
@@ -53,16 +53,16 @@ func (_mock *SearchProviderService) IndexSpace(ctx context.Context, in *v0.Index
|
||||
panic("no return value specified for IndexSpace")
|
||||
}
|
||||
|
||||
var r0 *v0.IndexSpaceResponse
|
||||
var r0 v0.SearchProvider_IndexSpaceService
|
||||
var r1 error
|
||||
if returnFunc, ok := ret.Get(0).(func(context.Context, *v0.IndexSpaceRequest, ...client.CallOption) (*v0.IndexSpaceResponse, error)); ok {
|
||||
if returnFunc, ok := ret.Get(0).(func(context.Context, *v0.IndexSpaceRequest, ...client.CallOption) (v0.SearchProvider_IndexSpaceService, error)); ok {
|
||||
return returnFunc(ctx, in, opts...)
|
||||
}
|
||||
if returnFunc, ok := ret.Get(0).(func(context.Context, *v0.IndexSpaceRequest, ...client.CallOption) *v0.IndexSpaceResponse); ok {
|
||||
if returnFunc, ok := ret.Get(0).(func(context.Context, *v0.IndexSpaceRequest, ...client.CallOption) v0.SearchProvider_IndexSpaceService); ok {
|
||||
r0 = returnFunc(ctx, in, opts...)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*v0.IndexSpaceResponse)
|
||||
r0 = ret.Get(0).(v0.SearchProvider_IndexSpaceService)
|
||||
}
|
||||
}
|
||||
if returnFunc, ok := ret.Get(1).(func(context.Context, *v0.IndexSpaceRequest, ...client.CallOption) error); ok {
|
||||
@@ -112,12 +112,12 @@ func (_c *SearchProviderService_IndexSpace_Call) Run(run func(ctx context.Contex
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *SearchProviderService_IndexSpace_Call) Return(indexSpaceResponse *v0.IndexSpaceResponse, err error) *SearchProviderService_IndexSpace_Call {
|
||||
_c.Call.Return(indexSpaceResponse, err)
|
||||
func (_c *SearchProviderService_IndexSpace_Call) Return(searchProvider_IndexSpaceService v0.SearchProvider_IndexSpaceService, err error) *SearchProviderService_IndexSpace_Call {
|
||||
_c.Call.Return(searchProvider_IndexSpaceService, err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *SearchProviderService_IndexSpace_Call) RunAndReturn(run func(ctx context.Context, in *v0.IndexSpaceRequest, opts ...client.CallOption) (*v0.IndexSpaceResponse, error)) *SearchProviderService_IndexSpace_Call {
|
||||
func (_c *SearchProviderService_IndexSpace_Call) RunAndReturn(run func(ctx context.Context, in *v0.IndexSpaceRequest, opts ...client.CallOption) (v0.SearchProvider_IndexSpaceService, error)) *SearchProviderService_IndexSpace_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
_ "google.golang.org/genproto/googleapis/api/annotations"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
durationpb "google.golang.org/protobuf/types/known/durationpb"
|
||||
_ "google.golang.org/protobuf/types/known/fieldmaskpb"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
@@ -310,6 +311,7 @@ type IndexSpaceRequest struct {
|
||||
SpaceId string `protobuf:"bytes,1,opt,name=space_id,json=spaceId,proto3" json:"space_id,omitempty"`
|
||||
UserId string `protobuf:"bytes,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
|
||||
ForceReindex bool `protobuf:"varint,3,opt,name=force_reindex,json=forceReindex,proto3" json:"force_reindex,omitempty"`
|
||||
Concurrency int32 `protobuf:"varint,4,opt,name=concurrency,proto3" json:"concurrency,omitempty"`
|
||||
}
|
||||
|
||||
func (x *IndexSpaceRequest) Reset() {
|
||||
@@ -365,10 +367,28 @@ func (x *IndexSpaceRequest) GetForceReindex() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *IndexSpaceRequest) GetConcurrency() int32 {
|
||||
if x != nil {
|
||||
return x.Concurrency
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type IndexSpaceResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// The id of the space that has just been indexed.
|
||||
SpaceId string `protobuf:"bytes,1,opt,name=space_id,json=spaceId,proto3" json:"space_id,omitempty"`
|
||||
// The duration it took to index this space.
|
||||
SpaceDuration *durationpb.Duration `protobuf:"bytes,2,opt,name=space_duration,json=spaceDuration,proto3" json:"space_duration,omitempty"`
|
||||
// The number of spaces that have been indexed so far.
|
||||
IndexedSpaces int64 `protobuf:"varint,3,opt,name=indexed_spaces,json=indexedSpaces,proto3" json:"indexed_spaces,omitempty"`
|
||||
// The total number of spaces that are being indexed.
|
||||
TotalSpaces int64 `protobuf:"varint,4,opt,name=total_spaces,json=totalSpaces,proto3" json:"total_spaces,omitempty"`
|
||||
// Contains an error message in case indexing this particular space failed.
|
||||
Error string `protobuf:"bytes,5,opt,name=error,proto3" json:"error,omitempty"`
|
||||
}
|
||||
|
||||
func (x *IndexSpaceResponse) Reset() {
|
||||
@@ -403,6 +423,41 @@ func (*IndexSpaceResponse) Descriptor() ([]byte, []int) {
|
||||
return file_opencloud_services_search_v0_search_proto_rawDescGZIP(), []int{5}
|
||||
}
|
||||
|
||||
func (x *IndexSpaceResponse) GetSpaceId() string {
|
||||
if x != nil {
|
||||
return x.SpaceId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *IndexSpaceResponse) GetSpaceDuration() *durationpb.Duration {
|
||||
if x != nil {
|
||||
return x.SpaceDuration
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *IndexSpaceResponse) GetIndexedSpaces() int64 {
|
||||
if x != nil {
|
||||
return x.IndexedSpaces
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *IndexSpaceResponse) GetTotalSpaces() int64 {
|
||||
if x != nil {
|
||||
return x.TotalSpaces
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *IndexSpaceResponse) GetError() string {
|
||||
if x != nil {
|
||||
return x.Error
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var File_opencloud_services_search_v0_search_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_opencloud_services_search_v0_search_proto_rawDesc = []byte{
|
||||
@@ -422,6 +477,8 @@ var file_opencloud_services_search_v0_search_proto_rawDesc = []byte{
|
||||
0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x62, 0x75, 0x66, 0x2f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x2e,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xae, 0x01, 0x0a, 0x0d, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68,
|
||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f,
|
||||
0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x42, 0x04, 0xe2, 0x41, 0x01, 0x01,
|
||||
@@ -465,68 +522,83 @@ var file_opencloud_services_search_v0_search_proto_rawDesc = []byte{
|
||||
0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x74, 0x6f,
|
||||
0x74, 0x61, 0x6c, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28,
|
||||
0x05, 0x52, 0x0c, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x22,
|
||||
0x6c, 0x0a, 0x11, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x53, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x64, 0x12,
|
||||
0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x66, 0x6f, 0x72, 0x63,
|
||||
0x65, 0x5f, 0x72, 0x65, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52,
|
||||
0x0c, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x52, 0x65, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x14, 0x0a,
|
||||
0x12, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x53, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x32, 0xb1, 0x02, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x50, 0x72,
|
||||
0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x85, 0x01, 0x0a, 0x06, 0x53, 0x65, 0x61, 0x72, 0x63,
|
||||
0x68, 0x12, 0x2b, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x73, 0x65,
|
||||
0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x76, 0x30,
|
||||
0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c,
|
||||
0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69,
|
||||
0x63, 0x65, 0x73, 0x2e, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x76, 0x30, 0x2e, 0x53, 0x65,
|
||||
0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3,
|
||||
0xe4, 0x93, 0x02, 0x1a, 0x3a, 0x01, 0x2a, 0x22, 0x15, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x30,
|
||||
0x2f, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2f, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x96,
|
||||
0x01, 0x0a, 0x0a, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x53, 0x70, 0x61, 0x63, 0x65, 0x12, 0x2f, 0x2e,
|
||||
0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
|
||||
0x65, 0x73, 0x2e, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x76, 0x30, 0x2e, 0x49, 0x6e, 0x64,
|
||||
0x65, 0x78, 0x53, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30,
|
||||
0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69,
|
||||
0x63, 0x65, 0x73, 0x2e, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x76, 0x30, 0x2e, 0x49, 0x6e,
|
||||
0x64, 0x65, 0x78, 0x53, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x3a, 0x01, 0x2a, 0x22, 0x1a, 0x2f, 0x61, 0x70,
|
||||
0x69, 0x2f, 0x76, 0x30, 0x2f, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2f, 0x69, 0x6e, 0x64, 0x65,
|
||||
0x78, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x65, 0x32, 0xa7, 0x01, 0x0a, 0x0d, 0x49, 0x6e, 0x64, 0x65,
|
||||
0x78, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x95, 0x01, 0x0a, 0x06, 0x53, 0x65,
|
||||
0x61, 0x72, 0x63, 0x68, 0x12, 0x30, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64,
|
||||
0x94, 0x01, 0x0a, 0x11, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x53, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69,
|
||||
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x64,
|
||||
0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x66, 0x6f, 0x72,
|
||||
0x63, 0x65, 0x5f, 0x72, 0x65, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08,
|
||||
0x52, 0x0c, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x52, 0x65, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x26,
|
||||
0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x04, 0x20,
|
||||
0x01, 0x28, 0x05, 0x42, 0x04, 0xe2, 0x41, 0x01, 0x01, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75,
|
||||
0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x22, 0xd1, 0x01, 0x0a, 0x12, 0x49, 0x6e, 0x64, 0x65, 0x78,
|
||||
0x53, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x19, 0x0a,
|
||||
0x08, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x07, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0x40, 0x0a, 0x0e, 0x73, 0x70, 0x61, 0x63,
|
||||
0x65, 0x5f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
|
||||
0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
|
||||
0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x73, 0x70, 0x61,
|
||||
0x63, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x69, 0x6e,
|
||||
0x64, 0x65, 0x78, 0x65, 0x64, 0x5f, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01,
|
||||
0x28, 0x03, 0x52, 0x0d, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x53, 0x70, 0x61, 0x63, 0x65,
|
||||
0x73, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x73, 0x70, 0x61, 0x63, 0x65,
|
||||
0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x53, 0x70,
|
||||
0x61, 0x63, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x05, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x32, 0xb3, 0x02, 0x0a, 0x0e, 0x53,
|
||||
0x65, 0x61, 0x72, 0x63, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x85, 0x01,
|
||||
0x0a, 0x06, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x2b, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63,
|
||||
0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x65,
|
||||
0x61, 0x72, 0x63, 0x68, 0x2e, 0x76, 0x30, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75,
|
||||
0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x65, 0x61, 0x72, 0x63,
|
||||
0x68, 0x2e, 0x76, 0x30, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x3a, 0x01, 0x2a, 0x22, 0x15,
|
||||
0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x30, 0x2f, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2f, 0x73,
|
||||
0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x98, 0x01, 0x0a, 0x0a, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x53,
|
||||
0x70, 0x61, 0x63, 0x65, 0x12, 0x2f, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64,
|
||||
0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68,
|
||||
0x2e, 0x76, 0x30, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f,
|
||||
0x75, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x65, 0x61, 0x72,
|
||||
0x63, 0x68, 0x2e, 0x76, 0x30, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x49, 0x6e, 0x64, 0x65,
|
||||
0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02,
|
||||
0x20, 0x3a, 0x01, 0x2a, 0x22, 0x1b, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x30, 0x2f, 0x73, 0x65,
|
||||
0x61, 0x72, 0x63, 0x68, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2f, 0x73, 0x65, 0x61, 0x72, 0x63,
|
||||
0x68, 0x42, 0xf2, 0x02, 0x5a, 0x4a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
|
||||
0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2d, 0x65, 0x75, 0x2f, 0x6f, 0x70,
|
||||
0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x67, 0x65, 0x6e,
|
||||
0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2f, 0x73,
|
||||
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2f, 0x76, 0x30,
|
||||
0x92, 0x41, 0xa2, 0x02, 0x12, 0xb7, 0x01, 0x0a, 0x10, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x6c, 0x6f,
|
||||
0x75, 0x64, 0x20, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x22, 0x51, 0x0a, 0x0e, 0x4f, 0x70, 0x65,
|
||||
0x6e, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x20, 0x47, 0x6d, 0x62, 0x48, 0x12, 0x29, 0x68, 0x74, 0x74,
|
||||
0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
|
||||
0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2d, 0x65, 0x75, 0x2f, 0x6f, 0x70, 0x65,
|
||||
0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x1a, 0x14, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x40,
|
||||
0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x65, 0x75, 0x2a, 0x49, 0x0a, 0x0a,
|
||||
0x41, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2d, 0x32, 0x2e, 0x30, 0x12, 0x3b, 0x68, 0x74, 0x74, 0x70,
|
||||
0x73, 0x3a, 0x2f, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f,
|
||||
0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2d, 0x65, 0x75, 0x2f, 0x6f, 0x70, 0x65, 0x6e,
|
||||
0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2f, 0x62, 0x6c, 0x6f, 0x62, 0x2f, 0x6d, 0x61, 0x69, 0x6e, 0x2f,
|
||||
0x4c, 0x49, 0x43, 0x45, 0x4e, 0x53, 0x45, 0x32, 0x05, 0x31, 0x2e, 0x30, 0x2e, 0x30, 0x2a, 0x02,
|
||||
0x01, 0x02, 0x32, 0x10, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f,
|
||||
0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x10, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x2f, 0x6a, 0x73, 0x6f, 0x6e, 0x72, 0x3e, 0x0a, 0x10, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f,
|
||||
0x70, 0x65, 0x72, 0x20, 0x4d, 0x61, 0x6e, 0x75, 0x61, 0x6c, 0x12, 0x2a, 0x68, 0x74, 0x74, 0x70,
|
||||
0x73, 0x3a, 0x2f, 0x2f, 0x64, 0x6f, 0x63, 0x73, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f,
|
||||
0x75, 0x64, 0x2e, 0x65, 0x75, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x73,
|
||||
0x65, 0x61, 0x72, 0x63, 0x68, 0x2f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x2e, 0x76, 0x30, 0x2e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x53, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75,
|
||||
0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x65, 0x61, 0x72, 0x63,
|
||||
0x68, 0x2e, 0x76, 0x30, 0x2e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x53, 0x70, 0x61, 0x63, 0x65, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x3a,
|
||||
0x01, 0x2a, 0x22, 0x1a, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x30, 0x2f, 0x73, 0x65, 0x61, 0x72,
|
||||
0x63, 0x68, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x65, 0x30, 0x01,
|
||||
0x32, 0xa7, 0x01, 0x0a, 0x0d, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64,
|
||||
0x65, 0x72, 0x12, 0x95, 0x01, 0x0a, 0x06, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x30, 0x2e,
|
||||
0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
|
||||
0x65, 0x73, 0x2e, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x76, 0x30, 0x2e, 0x53, 0x65, 0x61,
|
||||
0x72, 0x63, 0x68, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
||||
0x31, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76,
|
||||
0x69, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x76, 0x30, 0x2e, 0x53,
|
||||
0x65, 0x61, 0x72, 0x63, 0x68, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x3a, 0x01, 0x2a, 0x22, 0x1b, 0x2f,
|
||||
0x61, 0x70, 0x69, 0x2f, 0x76, 0x30, 0x2f, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2f, 0x69, 0x6e,
|
||||
0x64, 0x65, 0x78, 0x2f, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x42, 0xf2, 0x02, 0x5a, 0x4a, 0x67,
|
||||
0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c,
|
||||
0x6f, 0x75, 0x64, 0x2d, 0x65, 0x75, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64,
|
||||
0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x6f, 0x70,
|
||||
0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f,
|
||||
0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2f, 0x76, 0x30, 0x92, 0x41, 0xa2, 0x02, 0x12, 0xb7, 0x01,
|
||||
0x0a, 0x10, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x20, 0x73, 0x65, 0x61, 0x72,
|
||||
0x63, 0x68, 0x22, 0x51, 0x0a, 0x0e, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x20,
|
||||
0x47, 0x6d, 0x62, 0x48, 0x12, 0x29, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x67, 0x69,
|
||||
0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f,
|
||||
0x75, 0x64, 0x2d, 0x65, 0x75, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x1a,
|
||||
0x14, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x40, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f,
|
||||
0x75, 0x64, 0x2e, 0x65, 0x75, 0x2a, 0x49, 0x0a, 0x0a, 0x41, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2d,
|
||||
0x32, 0x2e, 0x30, 0x12, 0x3b, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x67, 0x69, 0x74,
|
||||
0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75,
|
||||
0x64, 0x2d, 0x65, 0x75, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2f, 0x62,
|
||||
0x6c, 0x6f, 0x62, 0x2f, 0x6d, 0x61, 0x69, 0x6e, 0x2f, 0x4c, 0x49, 0x43, 0x45, 0x4e, 0x53, 0x45,
|
||||
0x32, 0x05, 0x31, 0x2e, 0x30, 0x2e, 0x30, 0x2a, 0x02, 0x01, 0x02, 0x32, 0x10, 0x61, 0x70, 0x70,
|
||||
0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x10, 0x61,
|
||||
0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6a, 0x73, 0x6f, 0x6e, 0x72,
|
||||
0x3e, 0x0a, 0x10, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, 0x20, 0x4d, 0x61, 0x6e,
|
||||
0x75, 0x61, 0x6c, 0x12, 0x2a, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x64, 0x6f, 0x63,
|
||||
0x73, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x65, 0x75, 0x2f, 0x73,
|
||||
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2f, 0x62,
|
||||
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -551,23 +623,25 @@ var file_opencloud_services_search_v0_search_proto_goTypes = []interface{}{
|
||||
(*IndexSpaceResponse)(nil), // 5: opencloud.services.search.v0.IndexSpaceResponse
|
||||
(*v0.Reference)(nil), // 6: opencloud.messages.search.v0.Reference
|
||||
(*v0.Match)(nil), // 7: opencloud.messages.search.v0.Match
|
||||
(*durationpb.Duration)(nil), // 8: google.protobuf.Duration
|
||||
}
|
||||
var file_opencloud_services_search_v0_search_proto_depIdxs = []int32{
|
||||
6, // 0: opencloud.services.search.v0.SearchRequest.ref:type_name -> opencloud.messages.search.v0.Reference
|
||||
7, // 1: opencloud.services.search.v0.SearchResponse.matches:type_name -> opencloud.messages.search.v0.Match
|
||||
6, // 2: opencloud.services.search.v0.SearchIndexRequest.ref:type_name -> opencloud.messages.search.v0.Reference
|
||||
7, // 3: opencloud.services.search.v0.SearchIndexResponse.matches:type_name -> opencloud.messages.search.v0.Match
|
||||
0, // 4: opencloud.services.search.v0.SearchProvider.Search:input_type -> opencloud.services.search.v0.SearchRequest
|
||||
4, // 5: opencloud.services.search.v0.SearchProvider.IndexSpace:input_type -> opencloud.services.search.v0.IndexSpaceRequest
|
||||
2, // 6: opencloud.services.search.v0.IndexProvider.Search:input_type -> opencloud.services.search.v0.SearchIndexRequest
|
||||
1, // 7: opencloud.services.search.v0.SearchProvider.Search:output_type -> opencloud.services.search.v0.SearchResponse
|
||||
5, // 8: opencloud.services.search.v0.SearchProvider.IndexSpace:output_type -> opencloud.services.search.v0.IndexSpaceResponse
|
||||
3, // 9: opencloud.services.search.v0.IndexProvider.Search:output_type -> opencloud.services.search.v0.SearchIndexResponse
|
||||
7, // [7:10] is the sub-list for method output_type
|
||||
4, // [4:7] is the sub-list for method input_type
|
||||
4, // [4:4] is the sub-list for extension type_name
|
||||
4, // [4:4] is the sub-list for extension extendee
|
||||
0, // [0:4] is the sub-list for field type_name
|
||||
8, // 4: opencloud.services.search.v0.IndexSpaceResponse.space_duration:type_name -> google.protobuf.Duration
|
||||
0, // 5: opencloud.services.search.v0.SearchProvider.Search:input_type -> opencloud.services.search.v0.SearchRequest
|
||||
4, // 6: opencloud.services.search.v0.SearchProvider.IndexSpace:input_type -> opencloud.services.search.v0.IndexSpaceRequest
|
||||
2, // 7: opencloud.services.search.v0.IndexProvider.Search:input_type -> opencloud.services.search.v0.SearchIndexRequest
|
||||
1, // 8: opencloud.services.search.v0.SearchProvider.Search:output_type -> opencloud.services.search.v0.SearchResponse
|
||||
5, // 9: opencloud.services.search.v0.SearchProvider.IndexSpace:output_type -> opencloud.services.search.v0.IndexSpaceResponse
|
||||
3, // 10: opencloud.services.search.v0.IndexProvider.Search:output_type -> opencloud.services.search.v0.SearchIndexResponse
|
||||
8, // [8:11] is the sub-list for method output_type
|
||||
5, // [5:8] is the sub-list for method input_type
|
||||
5, // [5:5] is the sub-list for extension type_name
|
||||
5, // [5:5] is the sub-list for extension extendee
|
||||
0, // [0:5] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_opencloud_services_search_v0_search_proto_init() }
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
_ "github.com/opencloud-eu/opencloud/protogen/gen/opencloud/messages/search/v0"
|
||||
_ "google.golang.org/genproto/googleapis/api/annotations"
|
||||
proto "google.golang.org/protobuf/proto"
|
||||
_ "google.golang.org/protobuf/types/known/durationpb"
|
||||
_ "google.golang.org/protobuf/types/known/fieldmaskpb"
|
||||
math "math"
|
||||
)
|
||||
@@ -45,6 +46,7 @@ func NewSearchProviderEndpoints() []*api.Endpoint {
|
||||
Name: "SearchProvider.IndexSpace",
|
||||
Path: []string{"/api/v0/search/index-space"},
|
||||
Method: []string{"POST"},
|
||||
Stream: true,
|
||||
Handler: "rpc",
|
||||
},
|
||||
}
|
||||
@@ -54,7 +56,9 @@ func NewSearchProviderEndpoints() []*api.Endpoint {
|
||||
|
||||
type SearchProviderService interface {
|
||||
Search(ctx context.Context, in *SearchRequest, opts ...client.CallOption) (*SearchResponse, error)
|
||||
IndexSpace(ctx context.Context, in *IndexSpaceRequest, opts ...client.CallOption) (*IndexSpaceResponse, error)
|
||||
// IndexSpace (re)indexes one or all spaces. The response is streamed, sending
|
||||
// progress information after each space has been indexed.
|
||||
IndexSpace(ctx context.Context, in *IndexSpaceRequest, opts ...client.CallOption) (SearchProvider_IndexSpaceService, error)
|
||||
}
|
||||
|
||||
type searchProviderService struct {
|
||||
@@ -79,27 +83,73 @@ func (c *searchProviderService) Search(ctx context.Context, in *SearchRequest, o
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *searchProviderService) IndexSpace(ctx context.Context, in *IndexSpaceRequest, opts ...client.CallOption) (*IndexSpaceResponse, error) {
|
||||
req := c.c.NewRequest(c.name, "SearchProvider.IndexSpace", in)
|
||||
out := new(IndexSpaceResponse)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
func (c *searchProviderService) IndexSpace(ctx context.Context, in *IndexSpaceRequest, opts ...client.CallOption) (SearchProvider_IndexSpaceService, error) {
|
||||
req := c.c.NewRequest(c.name, "SearchProvider.IndexSpace", &IndexSpaceRequest{})
|
||||
stream, err := c.c.Stream(ctx, req, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
if err := stream.Send(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &searchProviderServiceIndexSpace{stream}, nil
|
||||
}
|
||||
|
||||
type SearchProvider_IndexSpaceService interface {
|
||||
Context() context.Context
|
||||
SendMsg(interface{}) error
|
||||
RecvMsg(interface{}) error
|
||||
CloseSend() error
|
||||
Close() error
|
||||
Recv() (*IndexSpaceResponse, error)
|
||||
}
|
||||
|
||||
type searchProviderServiceIndexSpace struct {
|
||||
stream client.Stream
|
||||
}
|
||||
|
||||
func (x *searchProviderServiceIndexSpace) CloseSend() error {
|
||||
return x.stream.CloseSend()
|
||||
}
|
||||
|
||||
func (x *searchProviderServiceIndexSpace) Close() error {
|
||||
return x.stream.Close()
|
||||
}
|
||||
|
||||
func (x *searchProviderServiceIndexSpace) Context() context.Context {
|
||||
return x.stream.Context()
|
||||
}
|
||||
|
||||
func (x *searchProviderServiceIndexSpace) SendMsg(m interface{}) error {
|
||||
return x.stream.Send(m)
|
||||
}
|
||||
|
||||
func (x *searchProviderServiceIndexSpace) RecvMsg(m interface{}) error {
|
||||
return x.stream.Recv(m)
|
||||
}
|
||||
|
||||
func (x *searchProviderServiceIndexSpace) Recv() (*IndexSpaceResponse, error) {
|
||||
m := new(IndexSpaceResponse)
|
||||
err := x.stream.Recv(m)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// Server API for SearchProvider service
|
||||
|
||||
type SearchProviderHandler interface {
|
||||
Search(context.Context, *SearchRequest, *SearchResponse) error
|
||||
IndexSpace(context.Context, *IndexSpaceRequest, *IndexSpaceResponse) error
|
||||
// IndexSpace (re)indexes one or all spaces. The response is streamed, sending
|
||||
// progress information after each space has been indexed.
|
||||
IndexSpace(context.Context, *IndexSpaceRequest, SearchProvider_IndexSpaceStream) error
|
||||
}
|
||||
|
||||
func RegisterSearchProviderHandler(s server.Server, hdlr SearchProviderHandler, opts ...server.HandlerOption) error {
|
||||
type searchProvider interface {
|
||||
Search(ctx context.Context, in *SearchRequest, out *SearchResponse) error
|
||||
IndexSpace(ctx context.Context, in *IndexSpaceRequest, out *IndexSpaceResponse) error
|
||||
IndexSpace(ctx context.Context, stream server.Stream) error
|
||||
}
|
||||
type SearchProvider struct {
|
||||
searchProvider
|
||||
@@ -115,6 +165,7 @@ func RegisterSearchProviderHandler(s server.Server, hdlr SearchProviderHandler,
|
||||
Name: "SearchProvider.IndexSpace",
|
||||
Path: []string{"/api/v0/search/index-space"},
|
||||
Method: []string{"POST"},
|
||||
Stream: true,
|
||||
Handler: "rpc",
|
||||
}))
|
||||
return s.Handle(s.NewHandler(&SearchProvider{h}, opts...))
|
||||
@@ -128,8 +179,44 @@ func (h *searchProviderHandler) Search(ctx context.Context, in *SearchRequest, o
|
||||
return h.SearchProviderHandler.Search(ctx, in, out)
|
||||
}
|
||||
|
||||
func (h *searchProviderHandler) IndexSpace(ctx context.Context, in *IndexSpaceRequest, out *IndexSpaceResponse) error {
|
||||
return h.SearchProviderHandler.IndexSpace(ctx, in, out)
|
||||
func (h *searchProviderHandler) IndexSpace(ctx context.Context, stream server.Stream) error {
|
||||
m := new(IndexSpaceRequest)
|
||||
if err := stream.Recv(m); err != nil {
|
||||
return err
|
||||
}
|
||||
return h.SearchProviderHandler.IndexSpace(ctx, m, &searchProviderIndexSpaceStream{stream})
|
||||
}
|
||||
|
||||
type SearchProvider_IndexSpaceStream interface {
|
||||
Context() context.Context
|
||||
SendMsg(interface{}) error
|
||||
RecvMsg(interface{}) error
|
||||
Close() error
|
||||
Send(*IndexSpaceResponse) error
|
||||
}
|
||||
|
||||
type searchProviderIndexSpaceStream struct {
|
||||
stream server.Stream
|
||||
}
|
||||
|
||||
func (x *searchProviderIndexSpaceStream) Close() error {
|
||||
return x.stream.Close()
|
||||
}
|
||||
|
||||
func (x *searchProviderIndexSpaceStream) Context() context.Context {
|
||||
return x.stream.Context()
|
||||
}
|
||||
|
||||
func (x *searchProviderIndexSpaceStream) SendMsg(m interface{}) error {
|
||||
return x.stream.Send(m)
|
||||
}
|
||||
|
||||
func (x *searchProviderIndexSpaceStream) RecvMsg(m interface{}) error {
|
||||
return x.stream.Recv(m)
|
||||
}
|
||||
|
||||
func (x *searchProviderIndexSpaceStream) Send(m *IndexSpaceResponse) error {
|
||||
return x.stream.Send(m)
|
||||
}
|
||||
|
||||
// Api Endpoints for IndexProvider service
|
||||
|
||||
@@ -1,346 +0,0 @@
|
||||
// Code generated by protoc-gen-microweb. DO NOT EDIT.
|
||||
// source: v0.proto
|
||||
|
||||
package v0
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-chi/render"
|
||||
"github.com/golang/protobuf/jsonpb"
|
||||
merrors "go-micro.dev/v4/errors"
|
||||
)
|
||||
|
||||
type webSearchProviderHandler struct {
|
||||
r chi.Router
|
||||
h SearchProviderHandler
|
||||
}
|
||||
|
||||
func (h *webSearchProviderHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
h.r.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
func (h *webSearchProviderHandler) Search(w http.ResponseWriter, r *http.Request) {
|
||||
req := &SearchRequest{}
|
||||
resp := &SearchResponse{}
|
||||
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusPreconditionFailed)
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.h.Search(
|
||||
r.Context(),
|
||||
req,
|
||||
resp,
|
||||
); err != nil {
|
||||
if merr, ok := merrors.As(err); ok && merr.Code == http.StatusNotFound {
|
||||
http.Error(w, err.Error(), http.StatusNotFound)
|
||||
} else {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
render.Status(r, http.StatusCreated)
|
||||
render.JSON(w, r, resp)
|
||||
}
|
||||
|
||||
func (h *webSearchProviderHandler) IndexSpace(w http.ResponseWriter, r *http.Request) {
|
||||
req := &IndexSpaceRequest{}
|
||||
resp := &IndexSpaceResponse{}
|
||||
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusPreconditionFailed)
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.h.IndexSpace(
|
||||
r.Context(),
|
||||
req,
|
||||
resp,
|
||||
); err != nil {
|
||||
if merr, ok := merrors.As(err); ok && merr.Code == http.StatusNotFound {
|
||||
http.Error(w, err.Error(), http.StatusNotFound)
|
||||
} else {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
render.Status(r, http.StatusCreated)
|
||||
render.JSON(w, r, resp)
|
||||
}
|
||||
|
||||
func RegisterSearchProviderWeb(r chi.Router, i SearchProviderHandler, middlewares ...func(http.Handler) http.Handler) {
|
||||
handler := &webSearchProviderHandler{
|
||||
r: r,
|
||||
h: i,
|
||||
}
|
||||
|
||||
r.MethodFunc("POST", "/api/v0/search/search", handler.Search)
|
||||
r.MethodFunc("POST", "/api/v0/search/index-space", handler.IndexSpace)
|
||||
}
|
||||
|
||||
type webIndexProviderHandler struct {
|
||||
r chi.Router
|
||||
h IndexProviderHandler
|
||||
}
|
||||
|
||||
func (h *webIndexProviderHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
h.r.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
func (h *webIndexProviderHandler) Search(w http.ResponseWriter, r *http.Request) {
|
||||
req := &SearchIndexRequest{}
|
||||
resp := &SearchIndexResponse{}
|
||||
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusPreconditionFailed)
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.h.Search(
|
||||
r.Context(),
|
||||
req,
|
||||
resp,
|
||||
); err != nil {
|
||||
if merr, ok := merrors.As(err); ok && merr.Code == http.StatusNotFound {
|
||||
http.Error(w, err.Error(), http.StatusNotFound)
|
||||
} else {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
render.Status(r, http.StatusCreated)
|
||||
render.JSON(w, r, resp)
|
||||
}
|
||||
|
||||
func RegisterIndexProviderWeb(r chi.Router, i IndexProviderHandler, middlewares ...func(http.Handler) http.Handler) {
|
||||
handler := &webIndexProviderHandler{
|
||||
r: r,
|
||||
h: i,
|
||||
}
|
||||
|
||||
r.MethodFunc("POST", "/api/v0/search/index/search", handler.Search)
|
||||
}
|
||||
|
||||
// SearchRequestJSONMarshaler describes the default jsonpb.Marshaler used by all
|
||||
// instances of SearchRequest. This struct is safe to replace or modify but
|
||||
// should not be done so concurrently.
|
||||
var SearchRequestJSONMarshaler = new(jsonpb.Marshaler)
|
||||
|
||||
// MarshalJSON satisfies the encoding/json Marshaler interface. This method
|
||||
// uses the more correct jsonpb package to correctly marshal the message.
|
||||
func (m *SearchRequest) MarshalJSON() ([]byte, error) {
|
||||
if m == nil {
|
||||
return json.Marshal(nil)
|
||||
}
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
|
||||
if err := SearchRequestJSONMarshaler.Marshal(buf, m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
var _ json.Marshaler = (*SearchRequest)(nil)
|
||||
|
||||
// SearchRequestJSONUnmarshaler describes the default jsonpb.Unmarshaler used by all
|
||||
// instances of SearchRequest. This struct is safe to replace or modify but
|
||||
// should not be done so concurrently.
|
||||
var SearchRequestJSONUnmarshaler = new(jsonpb.Unmarshaler)
|
||||
|
||||
// UnmarshalJSON satisfies the encoding/json Unmarshaler interface. This method
|
||||
// uses the more correct jsonpb package to correctly unmarshal the message.
|
||||
func (m *SearchRequest) UnmarshalJSON(b []byte) error {
|
||||
return SearchRequestJSONUnmarshaler.Unmarshal(bytes.NewReader(b), m)
|
||||
}
|
||||
|
||||
var _ json.Unmarshaler = (*SearchRequest)(nil)
|
||||
|
||||
// SearchResponseJSONMarshaler describes the default jsonpb.Marshaler used by all
|
||||
// instances of SearchResponse. This struct is safe to replace or modify but
|
||||
// should not be done so concurrently.
|
||||
var SearchResponseJSONMarshaler = new(jsonpb.Marshaler)
|
||||
|
||||
// MarshalJSON satisfies the encoding/json Marshaler interface. This method
|
||||
// uses the more correct jsonpb package to correctly marshal the message.
|
||||
func (m *SearchResponse) MarshalJSON() ([]byte, error) {
|
||||
if m == nil {
|
||||
return json.Marshal(nil)
|
||||
}
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
|
||||
if err := SearchResponseJSONMarshaler.Marshal(buf, m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
var _ json.Marshaler = (*SearchResponse)(nil)
|
||||
|
||||
// SearchResponseJSONUnmarshaler describes the default jsonpb.Unmarshaler used by all
|
||||
// instances of SearchResponse. This struct is safe to replace or modify but
|
||||
// should not be done so concurrently.
|
||||
var SearchResponseJSONUnmarshaler = new(jsonpb.Unmarshaler)
|
||||
|
||||
// UnmarshalJSON satisfies the encoding/json Unmarshaler interface. This method
|
||||
// uses the more correct jsonpb package to correctly unmarshal the message.
|
||||
func (m *SearchResponse) UnmarshalJSON(b []byte) error {
|
||||
return SearchResponseJSONUnmarshaler.Unmarshal(bytes.NewReader(b), m)
|
||||
}
|
||||
|
||||
var _ json.Unmarshaler = (*SearchResponse)(nil)
|
||||
|
||||
// SearchIndexRequestJSONMarshaler describes the default jsonpb.Marshaler used by all
|
||||
// instances of SearchIndexRequest. This struct is safe to replace or modify but
|
||||
// should not be done so concurrently.
|
||||
var SearchIndexRequestJSONMarshaler = new(jsonpb.Marshaler)
|
||||
|
||||
// MarshalJSON satisfies the encoding/json Marshaler interface. This method
|
||||
// uses the more correct jsonpb package to correctly marshal the message.
|
||||
func (m *SearchIndexRequest) MarshalJSON() ([]byte, error) {
|
||||
if m == nil {
|
||||
return json.Marshal(nil)
|
||||
}
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
|
||||
if err := SearchIndexRequestJSONMarshaler.Marshal(buf, m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
var _ json.Marshaler = (*SearchIndexRequest)(nil)
|
||||
|
||||
// SearchIndexRequestJSONUnmarshaler describes the default jsonpb.Unmarshaler used by all
|
||||
// instances of SearchIndexRequest. This struct is safe to replace or modify but
|
||||
// should not be done so concurrently.
|
||||
var SearchIndexRequestJSONUnmarshaler = new(jsonpb.Unmarshaler)
|
||||
|
||||
// UnmarshalJSON satisfies the encoding/json Unmarshaler interface. This method
|
||||
// uses the more correct jsonpb package to correctly unmarshal the message.
|
||||
func (m *SearchIndexRequest) UnmarshalJSON(b []byte) error {
|
||||
return SearchIndexRequestJSONUnmarshaler.Unmarshal(bytes.NewReader(b), m)
|
||||
}
|
||||
|
||||
var _ json.Unmarshaler = (*SearchIndexRequest)(nil)
|
||||
|
||||
// SearchIndexResponseJSONMarshaler describes the default jsonpb.Marshaler used by all
|
||||
// instances of SearchIndexResponse. This struct is safe to replace or modify but
|
||||
// should not be done so concurrently.
|
||||
var SearchIndexResponseJSONMarshaler = new(jsonpb.Marshaler)
|
||||
|
||||
// MarshalJSON satisfies the encoding/json Marshaler interface. This method
|
||||
// uses the more correct jsonpb package to correctly marshal the message.
|
||||
func (m *SearchIndexResponse) MarshalJSON() ([]byte, error) {
|
||||
if m == nil {
|
||||
return json.Marshal(nil)
|
||||
}
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
|
||||
if err := SearchIndexResponseJSONMarshaler.Marshal(buf, m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
var _ json.Marshaler = (*SearchIndexResponse)(nil)
|
||||
|
||||
// SearchIndexResponseJSONUnmarshaler describes the default jsonpb.Unmarshaler used by all
|
||||
// instances of SearchIndexResponse. This struct is safe to replace or modify but
|
||||
// should not be done so concurrently.
|
||||
var SearchIndexResponseJSONUnmarshaler = new(jsonpb.Unmarshaler)
|
||||
|
||||
// UnmarshalJSON satisfies the encoding/json Unmarshaler interface. This method
|
||||
// uses the more correct jsonpb package to correctly unmarshal the message.
|
||||
func (m *SearchIndexResponse) UnmarshalJSON(b []byte) error {
|
||||
return SearchIndexResponseJSONUnmarshaler.Unmarshal(bytes.NewReader(b), m)
|
||||
}
|
||||
|
||||
var _ json.Unmarshaler = (*SearchIndexResponse)(nil)
|
||||
|
||||
// IndexSpaceRequestJSONMarshaler describes the default jsonpb.Marshaler used by all
|
||||
// instances of IndexSpaceRequest. This struct is safe to replace or modify but
|
||||
// should not be done so concurrently.
|
||||
var IndexSpaceRequestJSONMarshaler = new(jsonpb.Marshaler)
|
||||
|
||||
// MarshalJSON satisfies the encoding/json Marshaler interface. This method
|
||||
// uses the more correct jsonpb package to correctly marshal the message.
|
||||
func (m *IndexSpaceRequest) MarshalJSON() ([]byte, error) {
|
||||
if m == nil {
|
||||
return json.Marshal(nil)
|
||||
}
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
|
||||
if err := IndexSpaceRequestJSONMarshaler.Marshal(buf, m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
var _ json.Marshaler = (*IndexSpaceRequest)(nil)
|
||||
|
||||
// IndexSpaceRequestJSONUnmarshaler describes the default jsonpb.Unmarshaler used by all
|
||||
// instances of IndexSpaceRequest. This struct is safe to replace or modify but
|
||||
// should not be done so concurrently.
|
||||
var IndexSpaceRequestJSONUnmarshaler = new(jsonpb.Unmarshaler)
|
||||
|
||||
// UnmarshalJSON satisfies the encoding/json Unmarshaler interface. This method
|
||||
// uses the more correct jsonpb package to correctly unmarshal the message.
|
||||
func (m *IndexSpaceRequest) UnmarshalJSON(b []byte) error {
|
||||
return IndexSpaceRequestJSONUnmarshaler.Unmarshal(bytes.NewReader(b), m)
|
||||
}
|
||||
|
||||
var _ json.Unmarshaler = (*IndexSpaceRequest)(nil)
|
||||
|
||||
// IndexSpaceResponseJSONMarshaler describes the default jsonpb.Marshaler used by all
|
||||
// instances of IndexSpaceResponse. This struct is safe to replace or modify but
|
||||
// should not be done so concurrently.
|
||||
var IndexSpaceResponseJSONMarshaler = new(jsonpb.Marshaler)
|
||||
|
||||
// MarshalJSON satisfies the encoding/json Marshaler interface. This method
|
||||
// uses the more correct jsonpb package to correctly marshal the message.
|
||||
func (m *IndexSpaceResponse) MarshalJSON() ([]byte, error) {
|
||||
if m == nil {
|
||||
return json.Marshal(nil)
|
||||
}
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
|
||||
if err := IndexSpaceResponseJSONMarshaler.Marshal(buf, m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
var _ json.Marshaler = (*IndexSpaceResponse)(nil)
|
||||
|
||||
// IndexSpaceResponseJSONUnmarshaler describes the default jsonpb.Unmarshaler used by all
|
||||
// instances of IndexSpaceResponse. This struct is safe to replace or modify but
|
||||
// should not be done so concurrently.
|
||||
var IndexSpaceResponseJSONUnmarshaler = new(jsonpb.Unmarshaler)
|
||||
|
||||
// UnmarshalJSON satisfies the encoding/json Unmarshaler interface. This method
|
||||
// uses the more correct jsonpb package to correctly unmarshal the message.
|
||||
func (m *IndexSpaceResponse) UnmarshalJSON(b []byte) error {
|
||||
return IndexSpaceResponseJSONUnmarshaler.Unmarshal(bytes.NewReader(b), m)
|
||||
}
|
||||
|
||||
var _ json.Unmarshaler = (*IndexSpaceResponse)(nil)
|
||||
@@ -34,12 +34,22 @@
|
||||
"paths": {
|
||||
"/api/v0/search/index-space": {
|
||||
"post": {
|
||||
"summary": "IndexSpace (re)indexes one or all spaces. The response is streamed, sending\nprogress information after each space has been indexed.",
|
||||
"operationId": "SearchProvider_IndexSpace",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"description": "A successful response.(streaming responses)",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/v0IndexSpaceResponse"
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"result": {
|
||||
"$ref": "#/definitions/v0IndexSpaceResponse"
|
||||
},
|
||||
"error": {
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
},
|
||||
"title": "Stream result of v0IndexSpaceResponse"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
@@ -288,6 +298,15 @@
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"motionPhoto": {
|
||||
"$ref": "#/definitions/v0MotionPhoto"
|
||||
},
|
||||
"video": {
|
||||
"$ref": "#/definitions/v0Video"
|
||||
},
|
||||
"livePhoto": {
|
||||
"$ref": "#/definitions/v0LivePhoto"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -332,11 +351,62 @@
|
||||
},
|
||||
"forceReindex": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"concurrency": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
}
|
||||
}
|
||||
},
|
||||
"v0IndexSpaceResponse": {
|
||||
"type": "object"
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"spaceId": {
|
||||
"type": "string",
|
||||
"description": "The id of the space that has just been indexed."
|
||||
},
|
||||
"spaceDuration": {
|
||||
"type": "string",
|
||||
"description": "The duration it took to index this space."
|
||||
},
|
||||
"indexedSpaces": {
|
||||
"type": "string",
|
||||
"format": "int64",
|
||||
"description": "The number of spaces that have been indexed so far."
|
||||
},
|
||||
"totalSpaces": {
|
||||
"type": "string",
|
||||
"format": "int64",
|
||||
"description": "The total number of spaces that are being indexed."
|
||||
},
|
||||
"error": {
|
||||
"type": "string",
|
||||
"description": "Contains an error message in case indexing this particular space failed."
|
||||
}
|
||||
}
|
||||
},
|
||||
"v0LivePhoto": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"contentId": {
|
||||
"type": "string"
|
||||
},
|
||||
"stillImageTimeUs": {
|
||||
"type": "string",
|
||||
"format": "int64"
|
||||
},
|
||||
"auto": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"vitalityScore": {
|
||||
"type": "number",
|
||||
"format": "double"
|
||||
},
|
||||
"vitalityScoringVersion": {
|
||||
"type": "string",
|
||||
"format": "int64"
|
||||
}
|
||||
}
|
||||
},
|
||||
"v0Match": {
|
||||
"type": "object",
|
||||
@@ -352,6 +422,23 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"v0MotionPhoto": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"version": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"presentationTimestampUs": {
|
||||
"type": "string",
|
||||
"format": "int64"
|
||||
},
|
||||
"videoSize": {
|
||||
"type": "string",
|
||||
"format": "int64"
|
||||
}
|
||||
}
|
||||
},
|
||||
"v0Photo": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -493,6 +580,49 @@
|
||||
"format": "int32"
|
||||
}
|
||||
}
|
||||
},
|
||||
"v0Video": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"audioBitsPerSample": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"audioChannels": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"audioFormat": {
|
||||
"type": "string"
|
||||
},
|
||||
"audioSamplesPerSecond": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"bitrate": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"duration": {
|
||||
"type": "string",
|
||||
"format": "int64"
|
||||
},
|
||||
"fourCC": {
|
||||
"type": "string"
|
||||
},
|
||||
"frameRate": {
|
||||
"type": "number",
|
||||
"format": "double"
|
||||
},
|
||||
"height": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"width": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"externalDocs": {
|
||||
|
||||
@@ -28,7 +28,9 @@ const (
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type SearchProviderClient interface {
|
||||
Search(ctx context.Context, in *SearchRequest, opts ...grpc.CallOption) (*SearchResponse, error)
|
||||
IndexSpace(ctx context.Context, in *IndexSpaceRequest, opts ...grpc.CallOption) (*IndexSpaceResponse, error)
|
||||
// IndexSpace (re)indexes one or all spaces. The response is streamed, sending
|
||||
// progress information after each space has been indexed.
|
||||
IndexSpace(ctx context.Context, in *IndexSpaceRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[IndexSpaceResponse], error)
|
||||
}
|
||||
|
||||
type searchProviderClient struct {
|
||||
@@ -49,22 +51,33 @@ func (c *searchProviderClient) Search(ctx context.Context, in *SearchRequest, op
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *searchProviderClient) IndexSpace(ctx context.Context, in *IndexSpaceRequest, opts ...grpc.CallOption) (*IndexSpaceResponse, error) {
|
||||
func (c *searchProviderClient) IndexSpace(ctx context.Context, in *IndexSpaceRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[IndexSpaceResponse], error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(IndexSpaceResponse)
|
||||
err := c.cc.Invoke(ctx, SearchProvider_IndexSpace_FullMethodName, in, out, cOpts...)
|
||||
stream, err := c.cc.NewStream(ctx, &SearchProvider_ServiceDesc.Streams[0], SearchProvider_IndexSpace_FullMethodName, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
x := &grpc.GenericClientStream[IndexSpaceRequest, IndexSpaceResponse]{ClientStream: stream}
|
||||
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := x.ClientStream.CloseSend(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type SearchProvider_IndexSpaceClient = grpc.ServerStreamingClient[IndexSpaceResponse]
|
||||
|
||||
// SearchProviderServer is the server API for SearchProvider service.
|
||||
// All implementations must embed UnimplementedSearchProviderServer
|
||||
// for forward compatibility.
|
||||
type SearchProviderServer interface {
|
||||
Search(context.Context, *SearchRequest) (*SearchResponse, error)
|
||||
IndexSpace(context.Context, *IndexSpaceRequest) (*IndexSpaceResponse, error)
|
||||
// IndexSpace (re)indexes one or all spaces. The response is streamed, sending
|
||||
// progress information after each space has been indexed.
|
||||
IndexSpace(*IndexSpaceRequest, grpc.ServerStreamingServer[IndexSpaceResponse]) error
|
||||
mustEmbedUnimplementedSearchProviderServer()
|
||||
}
|
||||
|
||||
@@ -78,8 +91,8 @@ type UnimplementedSearchProviderServer struct{}
|
||||
func (UnimplementedSearchProviderServer) Search(context.Context, *SearchRequest) (*SearchResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method Search not implemented")
|
||||
}
|
||||
func (UnimplementedSearchProviderServer) IndexSpace(context.Context, *IndexSpaceRequest) (*IndexSpaceResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method IndexSpace not implemented")
|
||||
func (UnimplementedSearchProviderServer) IndexSpace(*IndexSpaceRequest, grpc.ServerStreamingServer[IndexSpaceResponse]) error {
|
||||
return status.Error(codes.Unimplemented, "method IndexSpace not implemented")
|
||||
}
|
||||
func (UnimplementedSearchProviderServer) mustEmbedUnimplementedSearchProviderServer() {}
|
||||
func (UnimplementedSearchProviderServer) testEmbeddedByValue() {}
|
||||
@@ -120,24 +133,17 @@ func _SearchProvider_Search_Handler(srv interface{}, ctx context.Context, dec fu
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SearchProvider_IndexSpace_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(IndexSpaceRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
func _SearchProvider_IndexSpace_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
m := new(IndexSpaceRequest)
|
||||
if err := stream.RecvMsg(m); err != nil {
|
||||
return err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SearchProviderServer).IndexSpace(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: SearchProvider_IndexSpace_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SearchProviderServer).IndexSpace(ctx, req.(*IndexSpaceRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
return srv.(SearchProviderServer).IndexSpace(m, &grpc.GenericServerStream[IndexSpaceRequest, IndexSpaceResponse]{ServerStream: stream})
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type SearchProvider_IndexSpaceServer = grpc.ServerStreamingServer[IndexSpaceResponse]
|
||||
|
||||
// SearchProvider_ServiceDesc is the grpc.ServiceDesc for SearchProvider service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
@@ -149,12 +155,14 @@ var SearchProvider_ServiceDesc = grpc.ServiceDesc{
|
||||
MethodName: "Search",
|
||||
Handler: _SearchProvider_Search_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
MethodName: "IndexSpace",
|
||||
Handler: _SearchProvider_IndexSpace_Handler,
|
||||
StreamName: "IndexSpace",
|
||||
Handler: _SearchProvider_IndexSpace_Handler,
|
||||
ServerStreams: true,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "opencloud/services/search/v0/search.proto",
|
||||
}
|
||||
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
// Code generated by mockery; DO NOT EDIT.
|
||||
// github.com/vektra/mockery
|
||||
// template: testify
|
||||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/opencloud-eu/opencloud/protogen/gen/opencloud/services/thumbnails/v0"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
"go-micro.dev/v4/client"
|
||||
)
|
||||
|
||||
// NewThumbnailService creates a new instance of ThumbnailService. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
// The first argument is typically a *testing.T value.
|
||||
func NewThumbnailService(t interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}) *ThumbnailService {
|
||||
mock := &ThumbnailService{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
||||
|
||||
// ThumbnailService is an autogenerated mock type for the ThumbnailService type
|
||||
type ThumbnailService struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
type ThumbnailService_Expecter struct {
|
||||
mock *mock.Mock
|
||||
}
|
||||
|
||||
func (_m *ThumbnailService) EXPECT() *ThumbnailService_Expecter {
|
||||
return &ThumbnailService_Expecter{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// GetThumbnail provides a mock function for the type ThumbnailService
|
||||
func (_mock *ThumbnailService) GetThumbnail(ctx context.Context, in *v0.GetThumbnailRequest, opts ...client.CallOption) (*v0.GetThumbnailResponse, error) {
|
||||
var tmpRet mock.Arguments
|
||||
if len(opts) > 0 {
|
||||
tmpRet = _mock.Called(ctx, in, opts)
|
||||
} else {
|
||||
tmpRet = _mock.Called(ctx, in)
|
||||
}
|
||||
ret := tmpRet
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GetThumbnail")
|
||||
}
|
||||
|
||||
var r0 *v0.GetThumbnailResponse
|
||||
var r1 error
|
||||
if returnFunc, ok := ret.Get(0).(func(context.Context, *v0.GetThumbnailRequest, ...client.CallOption) (*v0.GetThumbnailResponse, error)); ok {
|
||||
return returnFunc(ctx, in, opts...)
|
||||
}
|
||||
if returnFunc, ok := ret.Get(0).(func(context.Context, *v0.GetThumbnailRequest, ...client.CallOption) *v0.GetThumbnailResponse); ok {
|
||||
r0 = returnFunc(ctx, in, opts...)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*v0.GetThumbnailResponse)
|
||||
}
|
||||
}
|
||||
if returnFunc, ok := ret.Get(1).(func(context.Context, *v0.GetThumbnailRequest, ...client.CallOption) error); ok {
|
||||
r1 = returnFunc(ctx, in, opts...)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// ThumbnailService_GetThumbnail_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetThumbnail'
|
||||
type ThumbnailService_GetThumbnail_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GetThumbnail is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - in *v0.GetThumbnailRequest
|
||||
// - opts ...client.CallOption
|
||||
func (_e *ThumbnailService_Expecter) GetThumbnail(ctx interface{}, in interface{}, opts ...interface{}) *ThumbnailService_GetThumbnail_Call {
|
||||
return &ThumbnailService_GetThumbnail_Call{Call: _e.mock.On("GetThumbnail",
|
||||
append([]interface{}{ctx, in}, opts...)...)}
|
||||
}
|
||||
|
||||
func (_c *ThumbnailService_GetThumbnail_Call) Run(run func(ctx context.Context, in *v0.GetThumbnailRequest, opts ...client.CallOption)) *ThumbnailService_GetThumbnail_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
var arg0 context.Context
|
||||
if args[0] != nil {
|
||||
arg0 = args[0].(context.Context)
|
||||
}
|
||||
var arg1 *v0.GetThumbnailRequest
|
||||
if args[1] != nil {
|
||||
arg1 = args[1].(*v0.GetThumbnailRequest)
|
||||
}
|
||||
var arg2 []client.CallOption
|
||||
var variadicArgs []client.CallOption
|
||||
if len(args) > 2 {
|
||||
variadicArgs = args[2].([]client.CallOption)
|
||||
}
|
||||
arg2 = variadicArgs
|
||||
run(
|
||||
arg0,
|
||||
arg1,
|
||||
arg2...,
|
||||
)
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *ThumbnailService_GetThumbnail_Call) Return(getThumbnailResponse *v0.GetThumbnailResponse, err error) *ThumbnailService_GetThumbnail_Call {
|
||||
_c.Call.Return(getThumbnailResponse, err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *ThumbnailService_GetThumbnail_Call) RunAndReturn(run func(ctx context.Context, in *v0.GetThumbnailRequest, opts ...client.CallOption) (*v0.GetThumbnailResponse, error)) *ThumbnailService_GetThumbnail_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
@@ -1,388 +0,0 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc (unknown)
|
||||
// source: opencloud/services/thumbnails/v0/thumbnails.proto
|
||||
|
||||
package v0
|
||||
|
||||
import (
|
||||
_ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options"
|
||||
v0 "github.com/opencloud-eu/opencloud/protogen/gen/opencloud/messages/thumbnails/v0"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// A request to retrieve a thumbnail
|
||||
type GetThumbnailRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// The path to the source image
|
||||
Filepath string `protobuf:"bytes,1,opt,name=filepath,proto3" json:"filepath,omitempty"`
|
||||
// The type to which the thumbnail should get encoded to.
|
||||
ThumbnailType v0.ThumbnailType `protobuf:"varint,2,opt,name=thumbnail_type,json=thumbnailType,proto3,enum=opencloud.messages.thumbnails.v0.ThumbnailType" json:"thumbnail_type,omitempty"`
|
||||
// The width of the thumbnail
|
||||
Width int32 `protobuf:"varint,3,opt,name=width,proto3" json:"width,omitempty"`
|
||||
// The height of the thumbnail
|
||||
Height int32 `protobuf:"varint,4,opt,name=height,proto3" json:"height,omitempty"`
|
||||
// Indicates which image processor to use
|
||||
Processor string `protobuf:"bytes,5,opt,name=processor,proto3" json:"processor,omitempty"`
|
||||
// Types that are assignable to Source:
|
||||
//
|
||||
// *GetThumbnailRequest_WebdavSource
|
||||
// *GetThumbnailRequest_Cs3Source
|
||||
Source isGetThumbnailRequest_Source `protobuf_oneof:"source"`
|
||||
}
|
||||
|
||||
func (x *GetThumbnailRequest) Reset() {
|
||||
*x = GetThumbnailRequest{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_opencloud_services_thumbnails_v0_thumbnails_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *GetThumbnailRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetThumbnailRequest) ProtoMessage() {}
|
||||
|
||||
func (x *GetThumbnailRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_opencloud_services_thumbnails_v0_thumbnails_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use GetThumbnailRequest.ProtoReflect.Descriptor instead.
|
||||
func (*GetThumbnailRequest) Descriptor() ([]byte, []int) {
|
||||
return file_opencloud_services_thumbnails_v0_thumbnails_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *GetThumbnailRequest) GetFilepath() string {
|
||||
if x != nil {
|
||||
return x.Filepath
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *GetThumbnailRequest) GetThumbnailType() v0.ThumbnailType {
|
||||
if x != nil {
|
||||
return x.ThumbnailType
|
||||
}
|
||||
return v0.ThumbnailType(0)
|
||||
}
|
||||
|
||||
func (x *GetThumbnailRequest) GetWidth() int32 {
|
||||
if x != nil {
|
||||
return x.Width
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *GetThumbnailRequest) GetHeight() int32 {
|
||||
if x != nil {
|
||||
return x.Height
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *GetThumbnailRequest) GetProcessor() string {
|
||||
if x != nil {
|
||||
return x.Processor
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *GetThumbnailRequest) GetSource() isGetThumbnailRequest_Source {
|
||||
if m != nil {
|
||||
return m.Source
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *GetThumbnailRequest) GetWebdavSource() *v0.WebdavSource {
|
||||
if x, ok := x.GetSource().(*GetThumbnailRequest_WebdavSource); ok {
|
||||
return x.WebdavSource
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *GetThumbnailRequest) GetCs3Source() *v0.CS3Source {
|
||||
if x, ok := x.GetSource().(*GetThumbnailRequest_Cs3Source); ok {
|
||||
return x.Cs3Source
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type isGetThumbnailRequest_Source interface {
|
||||
isGetThumbnailRequest_Source()
|
||||
}
|
||||
|
||||
type GetThumbnailRequest_WebdavSource struct {
|
||||
WebdavSource *v0.WebdavSource `protobuf:"bytes,6,opt,name=webdav_source,json=webdavSource,proto3,oneof"`
|
||||
}
|
||||
|
||||
type GetThumbnailRequest_Cs3Source struct {
|
||||
Cs3Source *v0.CS3Source `protobuf:"bytes,7,opt,name=cs3_source,json=cs3Source,proto3,oneof"`
|
||||
}
|
||||
|
||||
func (*GetThumbnailRequest_WebdavSource) isGetThumbnailRequest_Source() {}
|
||||
|
||||
func (*GetThumbnailRequest_Cs3Source) isGetThumbnailRequest_Source() {}
|
||||
|
||||
// The service response
|
||||
type GetThumbnailResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// The endpoint where the thumbnail can be downloaded.
|
||||
DataEndpoint string `protobuf:"bytes,1,opt,name=data_endpoint,json=dataEndpoint,proto3" json:"data_endpoint,omitempty"`
|
||||
// The transfer token to be able to download the thumbnail.
|
||||
TransferToken string `protobuf:"bytes,2,opt,name=transfer_token,json=transferToken,proto3" json:"transfer_token,omitempty"`
|
||||
// The mimetype of the thumbnail
|
||||
Mimetype string `protobuf:"bytes,3,opt,name=mimetype,proto3" json:"mimetype,omitempty"`
|
||||
}
|
||||
|
||||
func (x *GetThumbnailResponse) Reset() {
|
||||
*x = GetThumbnailResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_opencloud_services_thumbnails_v0_thumbnails_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *GetThumbnailResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetThumbnailResponse) ProtoMessage() {}
|
||||
|
||||
func (x *GetThumbnailResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_opencloud_services_thumbnails_v0_thumbnails_proto_msgTypes[1]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use GetThumbnailResponse.ProtoReflect.Descriptor instead.
|
||||
func (*GetThumbnailResponse) Descriptor() ([]byte, []int) {
|
||||
return file_opencloud_services_thumbnails_v0_thumbnails_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *GetThumbnailResponse) GetDataEndpoint() string {
|
||||
if x != nil {
|
||||
return x.DataEndpoint
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *GetThumbnailResponse) GetTransferToken() string {
|
||||
if x != nil {
|
||||
return x.TransferToken
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *GetThumbnailResponse) GetMimetype() string {
|
||||
if x != nil {
|
||||
return x.Mimetype
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var File_opencloud_services_thumbnails_v0_thumbnails_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_opencloud_services_thumbnails_v0_thumbnails_proto_rawDesc = []byte{
|
||||
0x0a, 0x31, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2f, 0x73, 0x65, 0x72, 0x76,
|
||||
0x69, 0x63, 0x65, 0x73, 0x2f, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x6e, 0x61, 0x69, 0x6c, 0x73, 0x2f,
|
||||
0x76, 0x30, 0x2f, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x6e, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x12, 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x73,
|
||||
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x6e, 0x61, 0x69,
|
||||
0x6c, 0x73, 0x2e, 0x76, 0x30, 0x1a, 0x31, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64,
|
||||
0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2f, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x6e,
|
||||
0x61, 0x69, 0x6c, 0x73, 0x2f, 0x76, 0x30, 0x2f, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x6e, 0x61, 0x69,
|
||||
0x6c, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63,
|
||||
0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2f, 0x6f,
|
||||
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x84, 0x03, 0x0a, 0x13, 0x47, 0x65, 0x74,
|
||||
0x54, 0x68, 0x75, 0x6d, 0x62, 0x6e, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x70, 0x61, 0x74, 0x68, 0x12, 0x56, 0x0a, 0x0e,
|
||||
0x74, 0x68, 0x75, 0x6d, 0x62, 0x6e, 0x61, 0x69, 0x6c, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02,
|
||||
0x20, 0x01, 0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64,
|
||||
0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x6e,
|
||||
0x61, 0x69, 0x6c, 0x73, 0x2e, 0x76, 0x30, 0x2e, 0x54, 0x68, 0x75, 0x6d, 0x62, 0x6e, 0x61, 0x69,
|
||||
0x6c, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0d, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x6e, 0x61, 0x69, 0x6c,
|
||||
0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x77, 0x69, 0x64, 0x74, 0x68, 0x18, 0x03, 0x20,
|
||||
0x01, 0x28, 0x05, 0x52, 0x05, 0x77, 0x69, 0x64, 0x74, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65,
|
||||
0x69, 0x67, 0x68, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67,
|
||||
0x68, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x18,
|
||||
0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72,
|
||||
0x12, 0x55, 0x0a, 0x0d, 0x77, 0x65, 0x62, 0x64, 0x61, 0x76, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63,
|
||||
0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c,
|
||||
0x6f, 0x75, 0x64, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x74, 0x68, 0x75,
|
||||
0x6d, 0x62, 0x6e, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x76, 0x30, 0x2e, 0x57, 0x65, 0x62, 0x64, 0x61,
|
||||
0x76, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x48, 0x00, 0x52, 0x0c, 0x77, 0x65, 0x62, 0x64, 0x61,
|
||||
0x76, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x4c, 0x0a, 0x0a, 0x63, 0x73, 0x33, 0x5f, 0x73,
|
||||
0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x6f, 0x70,
|
||||
0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73,
|
||||
0x2e, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x6e, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x76, 0x30, 0x2e, 0x43,
|
||||
0x53, 0x33, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x48, 0x00, 0x52, 0x09, 0x63, 0x73, 0x33, 0x53,
|
||||
0x6f, 0x75, 0x72, 0x63, 0x65, 0x42, 0x08, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22,
|
||||
0x7e, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x54, 0x68, 0x75, 0x6d, 0x62, 0x6e, 0x61, 0x69, 0x6c, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x61, 0x74, 0x61, 0x5f,
|
||||
0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c,
|
||||
0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x0e,
|
||||
0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x54, 0x6f,
|
||||
0x6b, 0x65, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x69, 0x6d, 0x65, 0x74, 0x79, 0x70, 0x65, 0x18,
|
||||
0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x69, 0x6d, 0x65, 0x74, 0x79, 0x70, 0x65, 0x32,
|
||||
0x91, 0x01, 0x0a, 0x10, 0x54, 0x68, 0x75, 0x6d, 0x62, 0x6e, 0x61, 0x69, 0x6c, 0x53, 0x65, 0x72,
|
||||
0x76, 0x69, 0x63, 0x65, 0x12, 0x7d, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x54, 0x68, 0x75, 0x6d, 0x62,
|
||||
0x6e, 0x61, 0x69, 0x6c, 0x12, 0x35, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64,
|
||||
0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x6e,
|
||||
0x61, 0x69, 0x6c, 0x73, 0x2e, 0x76, 0x30, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x68, 0x75, 0x6d, 0x62,
|
||||
0x6e, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x6f, 0x70,
|
||||
0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73,
|
||||
0x2e, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x6e, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x76, 0x30, 0x2e, 0x47,
|
||||
0x65, 0x74, 0x54, 0x68, 0x75, 0x6d, 0x62, 0x6e, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x42, 0xff, 0x02, 0x5a, 0x4f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
|
||||
0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2d, 0x65, 0x75, 0x2f,
|
||||
0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x67,
|
||||
0x65, 0x6e, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64,
|
||||
0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x6e,
|
||||
0x61, 0x69, 0x6c, 0x73, 0x2f, 0x76, 0x30, 0x92, 0x41, 0xaa, 0x02, 0x12, 0xbb, 0x01, 0x0a, 0x14,
|
||||
0x4f, 0x70, 0x65, 0x6e, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x20, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x6e,
|
||||
0x61, 0x69, 0x6c, 0x73, 0x22, 0x51, 0x0a, 0x0e, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x6c, 0x6f, 0x75,
|
||||
0x64, 0x20, 0x47, 0x6d, 0x62, 0x48, 0x12, 0x29, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f,
|
||||
0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63,
|
||||
0x6c, 0x6f, 0x75, 0x64, 0x2d, 0x65, 0x75, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75,
|
||||
0x64, 0x1a, 0x14, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x40, 0x6f, 0x70, 0x65, 0x6e, 0x63,
|
||||
0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x65, 0x75, 0x2a, 0x49, 0x0a, 0x0a, 0x41, 0x70, 0x61, 0x63, 0x68,
|
||||
0x65, 0x2d, 0x32, 0x2e, 0x30, 0x12, 0x3b, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x67,
|
||||
0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c,
|
||||
0x6f, 0x75, 0x64, 0x2d, 0x65, 0x75, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64,
|
||||
0x2f, 0x62, 0x6c, 0x6f, 0x62, 0x2f, 0x6d, 0x61, 0x69, 0x6e, 0x2f, 0x4c, 0x49, 0x43, 0x45, 0x4e,
|
||||
0x53, 0x45, 0x32, 0x05, 0x31, 0x2e, 0x30, 0x2e, 0x30, 0x2a, 0x02, 0x01, 0x02, 0x32, 0x10, 0x61,
|
||||
0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6a, 0x73, 0x6f, 0x6e, 0x3a,
|
||||
0x10, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6a, 0x73, 0x6f,
|
||||
0x6e, 0x72, 0x42, 0x0a, 0x10, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, 0x20, 0x4d,
|
||||
0x61, 0x6e, 0x75, 0x61, 0x6c, 0x12, 0x2e, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x64,
|
||||
0x6f, 0x63, 0x73, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x65, 0x75,
|
||||
0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x6e,
|
||||
0x61, 0x69, 0x6c, 0x73, 0x2f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_opencloud_services_thumbnails_v0_thumbnails_proto_rawDescOnce sync.Once
|
||||
file_opencloud_services_thumbnails_v0_thumbnails_proto_rawDescData = file_opencloud_services_thumbnails_v0_thumbnails_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_opencloud_services_thumbnails_v0_thumbnails_proto_rawDescGZIP() []byte {
|
||||
file_opencloud_services_thumbnails_v0_thumbnails_proto_rawDescOnce.Do(func() {
|
||||
file_opencloud_services_thumbnails_v0_thumbnails_proto_rawDescData = protoimpl.X.CompressGZIP(file_opencloud_services_thumbnails_v0_thumbnails_proto_rawDescData)
|
||||
})
|
||||
return file_opencloud_services_thumbnails_v0_thumbnails_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_opencloud_services_thumbnails_v0_thumbnails_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
||||
var file_opencloud_services_thumbnails_v0_thumbnails_proto_goTypes = []interface{}{
|
||||
(*GetThumbnailRequest)(nil), // 0: opencloud.services.thumbnails.v0.GetThumbnailRequest
|
||||
(*GetThumbnailResponse)(nil), // 1: opencloud.services.thumbnails.v0.GetThumbnailResponse
|
||||
(v0.ThumbnailType)(0), // 2: opencloud.messages.thumbnails.v0.ThumbnailType
|
||||
(*v0.WebdavSource)(nil), // 3: opencloud.messages.thumbnails.v0.WebdavSource
|
||||
(*v0.CS3Source)(nil), // 4: opencloud.messages.thumbnails.v0.CS3Source
|
||||
}
|
||||
var file_opencloud_services_thumbnails_v0_thumbnails_proto_depIdxs = []int32{
|
||||
2, // 0: opencloud.services.thumbnails.v0.GetThumbnailRequest.thumbnail_type:type_name -> opencloud.messages.thumbnails.v0.ThumbnailType
|
||||
3, // 1: opencloud.services.thumbnails.v0.GetThumbnailRequest.webdav_source:type_name -> opencloud.messages.thumbnails.v0.WebdavSource
|
||||
4, // 2: opencloud.services.thumbnails.v0.GetThumbnailRequest.cs3_source:type_name -> opencloud.messages.thumbnails.v0.CS3Source
|
||||
0, // 3: opencloud.services.thumbnails.v0.ThumbnailService.GetThumbnail:input_type -> opencloud.services.thumbnails.v0.GetThumbnailRequest
|
||||
1, // 4: opencloud.services.thumbnails.v0.ThumbnailService.GetThumbnail:output_type -> opencloud.services.thumbnails.v0.GetThumbnailResponse
|
||||
4, // [4:5] is the sub-list for method output_type
|
||||
3, // [3:4] is the sub-list for method input_type
|
||||
3, // [3:3] is the sub-list for extension type_name
|
||||
3, // [3:3] is the sub-list for extension extendee
|
||||
0, // [0:3] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_opencloud_services_thumbnails_v0_thumbnails_proto_init() }
|
||||
func file_opencloud_services_thumbnails_v0_thumbnails_proto_init() {
|
||||
if File_opencloud_services_thumbnails_v0_thumbnails_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_opencloud_services_thumbnails_v0_thumbnails_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*GetThumbnailRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_opencloud_services_thumbnails_v0_thumbnails_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*GetThumbnailResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
file_opencloud_services_thumbnails_v0_thumbnails_proto_msgTypes[0].OneofWrappers = []interface{}{
|
||||
(*GetThumbnailRequest_WebdavSource)(nil),
|
||||
(*GetThumbnailRequest_Cs3Source)(nil),
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_opencloud_services_thumbnails_v0_thumbnails_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 2,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
GoTypes: file_opencloud_services_thumbnails_v0_thumbnails_proto_goTypes,
|
||||
DependencyIndexes: file_opencloud_services_thumbnails_v0_thumbnails_proto_depIdxs,
|
||||
MessageInfos: file_opencloud_services_thumbnails_v0_thumbnails_proto_msgTypes,
|
||||
}.Build()
|
||||
File_opencloud_services_thumbnails_v0_thumbnails_proto = out.File
|
||||
file_opencloud_services_thumbnails_v0_thumbnails_proto_rawDesc = nil
|
||||
file_opencloud_services_thumbnails_v0_thumbnails_proto_goTypes = nil
|
||||
file_opencloud_services_thumbnails_v0_thumbnails_proto_depIdxs = nil
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
// Code generated by protoc-gen-micro. DO NOT EDIT.
|
||||
// source: opencloud/services/thumbnails/v0/thumbnails.proto
|
||||
|
||||
package v0
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
_ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options"
|
||||
_ "github.com/opencloud-eu/opencloud/protogen/gen/opencloud/messages/thumbnails/v0"
|
||||
proto "google.golang.org/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
import (
|
||||
context "context"
|
||||
api "go-micro.dev/v4/api"
|
||||
client "go-micro.dev/v4/client"
|
||||
server "go-micro.dev/v4/server"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ api.Endpoint
|
||||
var _ context.Context
|
||||
var _ client.Option
|
||||
var _ server.Option
|
||||
|
||||
// Api Endpoints for ThumbnailService service
|
||||
|
||||
func NewThumbnailServiceEndpoints() []*api.Endpoint {
|
||||
return []*api.Endpoint{}
|
||||
}
|
||||
|
||||
// Client API for ThumbnailService service
|
||||
|
||||
type ThumbnailService interface {
|
||||
// Generates the thumbnail and returns it.
|
||||
GetThumbnail(ctx context.Context, in *GetThumbnailRequest, opts ...client.CallOption) (*GetThumbnailResponse, error)
|
||||
}
|
||||
|
||||
type thumbnailService struct {
|
||||
c client.Client
|
||||
name string
|
||||
}
|
||||
|
||||
func NewThumbnailService(name string, c client.Client) ThumbnailService {
|
||||
return &thumbnailService{
|
||||
c: c,
|
||||
name: name,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *thumbnailService) GetThumbnail(ctx context.Context, in *GetThumbnailRequest, opts ...client.CallOption) (*GetThumbnailResponse, error) {
|
||||
req := c.c.NewRequest(c.name, "ThumbnailService.GetThumbnail", in)
|
||||
out := new(GetThumbnailResponse)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for ThumbnailService service
|
||||
|
||||
type ThumbnailServiceHandler interface {
|
||||
// Generates the thumbnail and returns it.
|
||||
GetThumbnail(context.Context, *GetThumbnailRequest, *GetThumbnailResponse) error
|
||||
}
|
||||
|
||||
func RegisterThumbnailServiceHandler(s server.Server, hdlr ThumbnailServiceHandler, opts ...server.HandlerOption) error {
|
||||
type thumbnailService interface {
|
||||
GetThumbnail(ctx context.Context, in *GetThumbnailRequest, out *GetThumbnailResponse) error
|
||||
}
|
||||
type ThumbnailService struct {
|
||||
thumbnailService
|
||||
}
|
||||
h := &thumbnailServiceHandler{hdlr}
|
||||
return s.Handle(s.NewHandler(&ThumbnailService{h}, opts...))
|
||||
}
|
||||
|
||||
type thumbnailServiceHandler struct {
|
||||
ThumbnailServiceHandler
|
||||
}
|
||||
|
||||
func (h *thumbnailServiceHandler) GetThumbnail(ctx context.Context, in *GetThumbnailRequest, out *GetThumbnailResponse) error {
|
||||
return h.ThumbnailServiceHandler.GetThumbnail(ctx, in, out)
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"title": "OpenCloud thumbnails",
|
||||
"version": "1.0.0",
|
||||
"contact": {
|
||||
"name": "OpenCloud GmbH",
|
||||
"url": "https://github.com/opencloud-eu/opencloud",
|
||||
"email": "support@opencloud.eu"
|
||||
},
|
||||
"license": {
|
||||
"name": "Apache-2.0",
|
||||
"url": "https://github.com/opencloud-eu/opencloud/blob/main/LICENSE"
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
{
|
||||
"name": "ThumbnailService"
|
||||
}
|
||||
],
|
||||
"schemes": [
|
||||
"http",
|
||||
"https"
|
||||
],
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"paths": {},
|
||||
"definitions": {
|
||||
"protobufAny": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"@type": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": {}
|
||||
},
|
||||
"rpcStatus": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"code": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"details": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/protobufAny"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"v0CS3Source": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"authorization": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"v0GetThumbnailResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dataEndpoint": {
|
||||
"type": "string",
|
||||
"description": "The endpoint where the thumbnail can be downloaded."
|
||||
},
|
||||
"transferToken": {
|
||||
"type": "string",
|
||||
"description": "The transfer token to be able to download the thumbnail."
|
||||
},
|
||||
"mimetype": {
|
||||
"type": "string",
|
||||
"title": "The mimetype of the thumbnail"
|
||||
}
|
||||
},
|
||||
"title": "The service response"
|
||||
},
|
||||
"v0ThumbnailType": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"PNG",
|
||||
"JPG",
|
||||
"GIF"
|
||||
],
|
||||
"default": "PNG",
|
||||
"description": "The file types to which the thumbnail can be encoded to.\n\n - PNG: Represents PNG type\n - JPG: Represents JPG type\n - GIF: Represents GIF type"
|
||||
},
|
||||
"v0WebdavSource": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "REQUIRED."
|
||||
},
|
||||
"isPublicLink": {
|
||||
"type": "boolean",
|
||||
"description": "REQUIRED."
|
||||
},
|
||||
"webdavAuthorization": {
|
||||
"type": "string",
|
||||
"description": "OPTIONAL."
|
||||
},
|
||||
"revaAuthorization": {
|
||||
"type": "string",
|
||||
"description": "OPTIONAL."
|
||||
},
|
||||
"publicLinkToken": {
|
||||
"type": "string",
|
||||
"description": "OPTIONAL."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"externalDocs": {
|
||||
"description": "Developer Manual",
|
||||
"url": "https://docs.opencloud.eu/services/thumbnails/"
|
||||
}
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.6.2
|
||||
// - protoc (unknown)
|
||||
// source: opencloud/services/thumbnails/v0/thumbnails.proto
|
||||
|
||||
package v0
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.64.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
ThumbnailService_GetThumbnail_FullMethodName = "/opencloud.services.thumbnails.v0.ThumbnailService/GetThumbnail"
|
||||
)
|
||||
|
||||
// ThumbnailServiceClient is the client API for ThumbnailService service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
//
|
||||
// A Service for handling thumbnail generation
|
||||
type ThumbnailServiceClient interface {
|
||||
// Generates the thumbnail and returns it.
|
||||
GetThumbnail(ctx context.Context, in *GetThumbnailRequest, opts ...grpc.CallOption) (*GetThumbnailResponse, error)
|
||||
}
|
||||
|
||||
type thumbnailServiceClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewThumbnailServiceClient(cc grpc.ClientConnInterface) ThumbnailServiceClient {
|
||||
return &thumbnailServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *thumbnailServiceClient) GetThumbnail(ctx context.Context, in *GetThumbnailRequest, opts ...grpc.CallOption) (*GetThumbnailResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(GetThumbnailResponse)
|
||||
err := c.cc.Invoke(ctx, ThumbnailService_GetThumbnail_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// ThumbnailServiceServer is the server API for ThumbnailService service.
|
||||
// All implementations must embed UnimplementedThumbnailServiceServer
|
||||
// for forward compatibility.
|
||||
//
|
||||
// A Service for handling thumbnail generation
|
||||
type ThumbnailServiceServer interface {
|
||||
// Generates the thumbnail and returns it.
|
||||
GetThumbnail(context.Context, *GetThumbnailRequest) (*GetThumbnailResponse, error)
|
||||
mustEmbedUnimplementedThumbnailServiceServer()
|
||||
}
|
||||
|
||||
// UnimplementedThumbnailServiceServer must be embedded to have
|
||||
// forward compatible implementations.
|
||||
//
|
||||
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||
// pointer dereference when methods are called.
|
||||
type UnimplementedThumbnailServiceServer struct{}
|
||||
|
||||
func (UnimplementedThumbnailServiceServer) GetThumbnail(context.Context, *GetThumbnailRequest) (*GetThumbnailResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetThumbnail not implemented")
|
||||
}
|
||||
func (UnimplementedThumbnailServiceServer) mustEmbedUnimplementedThumbnailServiceServer() {}
|
||||
func (UnimplementedThumbnailServiceServer) testEmbeddedByValue() {}
|
||||
|
||||
// UnsafeThumbnailServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to ThumbnailServiceServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeThumbnailServiceServer interface {
|
||||
mustEmbedUnimplementedThumbnailServiceServer()
|
||||
}
|
||||
|
||||
func RegisterThumbnailServiceServer(s grpc.ServiceRegistrar, srv ThumbnailServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedThumbnailServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||
t.testEmbeddedByValue()
|
||||
}
|
||||
s.RegisterService(&ThumbnailService_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _ThumbnailService_GetThumbnail_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(GetThumbnailRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ThumbnailServiceServer).GetThumbnail(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: ThumbnailService_GetThumbnail_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ThumbnailServiceServer).GetThumbnail(ctx, req.(*GetThumbnailRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// ThumbnailService_ServiceDesc is the grpc.ServiceDesc for ThumbnailService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var ThumbnailService_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "opencloud.services.thumbnails.v0.ThumbnailService",
|
||||
HandlerType: (*ThumbnailServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "GetThumbnail",
|
||||
Handler: _ThumbnailService_GetThumbnail_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "opencloud/services/thumbnails/v0/thumbnails.proto",
|
||||
}
|
||||
@@ -31,7 +31,9 @@ plugins:
|
||||
opencloud.services.eventhistory.v0;\
|
||||
opencloud.messages.eventhistory.v0;\
|
||||
opencloud.services.policies.v0;\
|
||||
opencloud.messages.policies.v0"
|
||||
opencloud.messages.policies.v0;\
|
||||
opencloud.services.search.v0;\
|
||||
opencloud.messages.search.v0"
|
||||
|
||||
- name: openapiv2
|
||||
path: ../../.bingo/protoc-gen-openapiv2
|
||||
|
||||
@@ -59,6 +59,33 @@ message Photo {
|
||||
optional google.protobuf.Timestamp takenDateTime = 9;
|
||||
}
|
||||
|
||||
message Video {
|
||||
optional int32 audioBitsPerSample = 1;
|
||||
optional int32 audioChannels = 2;
|
||||
optional string audioFormat = 3;
|
||||
optional int32 audioSamplesPerSecond = 4;
|
||||
optional int32 bitrate = 5;
|
||||
optional int64 duration = 6;
|
||||
optional string fourCC = 7;
|
||||
optional double frameRate = 8;
|
||||
optional int32 height = 9;
|
||||
optional int32 width = 10;
|
||||
}
|
||||
|
||||
message MotionPhoto {
|
||||
optional int32 version = 1;
|
||||
optional int64 presentationTimestampUs = 2;
|
||||
optional int64 videoSize = 3;
|
||||
}
|
||||
|
||||
message LivePhoto {
|
||||
optional string contentId = 1;
|
||||
optional int64 stillImageTimeUs = 2;
|
||||
optional bool auto = 3;
|
||||
optional double vitalityScore = 4;
|
||||
optional int64 vitalityScoringVersion = 5;
|
||||
}
|
||||
|
||||
message Entity {
|
||||
Reference ref = 1;
|
||||
ResourceID id = 2;
|
||||
@@ -80,6 +107,9 @@ message Entity {
|
||||
Image image = 18;
|
||||
Photo photo = 19;
|
||||
repeated string favorites = 20;
|
||||
MotionPhoto motionPhoto = 21;
|
||||
Video video = 22;
|
||||
LivePhoto livePhoto = 23;
|
||||
}
|
||||
|
||||
message Match {
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package opencloud.messages.thumbnails.v0;
|
||||
|
||||
option go_package = "github.com/opencloud-eu/opencloud/protogen/gen/opencloud/messages/thumbnails/v0";
|
||||
|
||||
message WebdavSource {
|
||||
// REQUIRED.
|
||||
string url = 1;
|
||||
// REQUIRED.
|
||||
bool is_public_link = 2;
|
||||
// OPTIONAL.
|
||||
string webdav_authorization = 3;
|
||||
// OPTIONAL.
|
||||
string reva_authorization = 4;
|
||||
// OPTIONAL.
|
||||
string public_link_token = 5;
|
||||
}
|
||||
|
||||
message CS3Source {
|
||||
string path = 1;
|
||||
string authorization = 2;
|
||||
}
|
||||
|
||||
// The file types to which the thumbnail can be encoded to.
|
||||
enum ThumbnailType {
|
||||
PNG = 0; // Represents PNG type
|
||||
JPG = 1; // Represents JPG type
|
||||
GIF = 2; // Represents GIF type
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import "protoc-gen-openapiv2/options/annotations.proto";
|
||||
import "google/api/field_behavior.proto";
|
||||
import "google/api/annotations.proto";
|
||||
import "google/protobuf/field_mask.proto";
|
||||
import "google/protobuf/duration.proto";
|
||||
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
|
||||
info: {
|
||||
@@ -41,7 +42,9 @@ service SearchProvider {
|
||||
body: "*"
|
||||
};
|
||||
};
|
||||
rpc IndexSpace(IndexSpaceRequest) returns (IndexSpaceResponse) {
|
||||
// IndexSpace (re)indexes one or all spaces. The response is streamed, sending
|
||||
// progress information after each space has been indexed.
|
||||
rpc IndexSpace(IndexSpaceRequest) returns (stream IndexSpaceResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/api/v0/search/index-space",
|
||||
body: "*"
|
||||
@@ -105,7 +108,18 @@ message IndexSpaceRequest {
|
||||
string space_id = 1;
|
||||
string user_id = 2;
|
||||
bool force_reindex = 3;
|
||||
int32 concurrency = 4 [(google.api.field_behavior) = OPTIONAL];
|
||||
}
|
||||
|
||||
message IndexSpaceResponse {
|
||||
// The id of the space that has just been indexed.
|
||||
string space_id = 1;
|
||||
// The duration it took to index this space.
|
||||
google.protobuf.Duration space_duration = 2;
|
||||
// The number of spaces that have been indexed so far.
|
||||
int64 indexed_spaces = 3;
|
||||
// The total number of spaces that are being indexed.
|
||||
int64 total_spaces = 4;
|
||||
// Contains an error message in case indexing this particular space failed.
|
||||
string error = 5;
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package opencloud.services.thumbnails.v0;
|
||||
|
||||
option go_package = "github.com/opencloud-eu/opencloud/protogen/gen/opencloud/services/thumbnails/v0";
|
||||
|
||||
import "opencloud/messages/thumbnails/v0/thumbnails.proto";
|
||||
import "protoc-gen-openapiv2/options/annotations.proto";
|
||||
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
|
||||
info: {
|
||||
title: "OpenCloud thumbnails";
|
||||
version: "1.0.0";
|
||||
contact: {
|
||||
name: "OpenCloud GmbH";
|
||||
url: "https://github.com/opencloud-eu/opencloud";
|
||||
email: "support@opencloud.eu";
|
||||
};
|
||||
license: {
|
||||
name: "Apache-2.0";
|
||||
url: "https://github.com/opencloud-eu/opencloud/blob/main/LICENSE";
|
||||
};
|
||||
};
|
||||
schemes: HTTP;
|
||||
schemes: HTTPS;
|
||||
consumes: "application/json";
|
||||
produces: "application/json";
|
||||
external_docs: {
|
||||
description: "Developer Manual";
|
||||
url: "https://docs.opencloud.eu/services/thumbnails/";
|
||||
};
|
||||
};
|
||||
|
||||
// A Service for handling thumbnail generation
|
||||
service ThumbnailService {
|
||||
// Generates the thumbnail and returns it.
|
||||
rpc GetThumbnail(GetThumbnailRequest) returns (GetThumbnailResponse);
|
||||
}
|
||||
|
||||
// A request to retrieve a thumbnail
|
||||
message GetThumbnailRequest {
|
||||
// The path to the source image
|
||||
string filepath = 1;
|
||||
// The type to which the thumbnail should get encoded to.
|
||||
opencloud.messages.thumbnails.v0.ThumbnailType thumbnail_type = 2;
|
||||
// The width of the thumbnail
|
||||
int32 width = 3;
|
||||
// The height of the thumbnail
|
||||
int32 height = 4;
|
||||
// Indicates which image processor to use
|
||||
string processor = 5;
|
||||
oneof source {
|
||||
opencloud.messages.thumbnails.v0.WebdavSource webdav_source = 6;
|
||||
opencloud.messages.thumbnails.v0.CS3Source cs3_source = 7;
|
||||
}
|
||||
}
|
||||
|
||||
// The service response
|
||||
message GetThumbnailResponse {
|
||||
// The endpoint where the thumbnail can be downloaded.
|
||||
string data_endpoint = 1;
|
||||
// The transfer token to be able to download the thumbnail.
|
||||
string transfer_token = 2;
|
||||
// The mimetype of the thumbnail
|
||||
string mimetype = 3;
|
||||
}
|
||||
@@ -73,6 +73,38 @@ export default {
|
||||
const latestTag = tags.pop() || "v0.0.0";
|
||||
return compareVersions(latestTag, nextVersion) === -1;
|
||||
},
|
||||
getReleaseDescription: async ({ nextVersion }) => {
|
||||
const note =
|
||||
"> [!IMPORTANT]\n" +
|
||||
"> This is a rolling release. Learn here about the [release types and lifecycle](https://docs.opencloud.eu/docs/admin/resources/lifecycle#release-types).\n\n";
|
||||
|
||||
// Exclude the "📦️ Dependencies" section from the release description
|
||||
const section = removeChangelogSubsection(
|
||||
await getChangelogSection(nextVersion),
|
||||
"📦️ Dependencies"
|
||||
);
|
||||
|
||||
return `${note}${section}`;
|
||||
},
|
||||
};
|
||||
// helper functions
|
||||
const getChangelogSection = async (nextVersion: string) => {
|
||||
const { promises: fs } = await import("fs");
|
||||
const changelog = await fs.readFile("CHANGELOG.md", "utf-8").catch(() => "");
|
||||
|
||||
const section = changelog
|
||||
.split(/\n(?=## \[)/)
|
||||
.find((s) => s.startsWith(`## [${nextVersion}]`));
|
||||
|
||||
return section?.trim() ?? "";
|
||||
};
|
||||
|
||||
const removeChangelogSubsection = (section: string, heading: string) => {
|
||||
return section
|
||||
.split(/\n(?=### )/)
|
||||
.filter((s) => !s.startsWith(`### ${heading}`))
|
||||
.join("\n")
|
||||
.trim();
|
||||
};
|
||||
|
||||
const parseVersion = (tag: string) => {
|
||||
|
||||
@@ -9,9 +9,7 @@ import (
|
||||
"github.com/opencloud-eu/reva/v2/pkg/events"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/events/stream"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/store"
|
||||
"github.com/spf13/cobra"
|
||||
microstore "go-micro.dev/v4/store"
|
||||
|
||||
"github.com/opencloud-eu/opencloud/pkg/config/configlog"
|
||||
"github.com/opencloud-eu/opencloud/pkg/generators"
|
||||
@@ -77,15 +75,6 @@ func Server(cfg *config.Config) *cobra.Command {
|
||||
return err
|
||||
}
|
||||
|
||||
evStore := store.Create(
|
||||
store.Store(cfg.Store.Store),
|
||||
store.TTL(cfg.Store.TTL),
|
||||
microstore.Nodes(cfg.Store.Nodes...),
|
||||
microstore.Database(cfg.Store.Database),
|
||||
microstore.Table(cfg.Store.Table),
|
||||
store.Authentication(cfg.Store.AuthUsername, cfg.Store.AuthPassword),
|
||||
)
|
||||
|
||||
tm, err := pool.StringToTLSMode(cfg.GRPCClientTLS.Mode)
|
||||
if err != nil {
|
||||
logger.Error().Err(err).Msg("Failed to parse tls mode")
|
||||
@@ -120,7 +109,6 @@ func Server(cfg *config.Config) *cobra.Command {
|
||||
http.Context(ctx), // NOTE: not passing this "option" leads to a panic in go-micro
|
||||
http.TraceProvider(tracerProvider),
|
||||
http.Stream(evStream),
|
||||
http.Store(evStore),
|
||||
http.GatewaySelector(gatewaySelector),
|
||||
http.HistoryClient(hClient),
|
||||
http.ValueClient(vClient),
|
||||
|
||||
@@ -50,13 +50,15 @@ type Events struct {
|
||||
|
||||
// Store configures the store to use
|
||||
type Store struct {
|
||||
Store string `yaml:"store" env:"OC_PERSISTENT_STORE;ACTIVITYLOG_STORE" desc:"The type of the store. Supported values are: 'memory', 'nats-js-kv', 'redis-sentinel', 'noop'. See the text description for details." introductionVersion:"1.0.0"`
|
||||
Nodes []string `yaml:"nodes" env:"OC_PERSISTENT_STORE_NODES;ACTIVITYLOG_STORE_NODES" desc:"A list of nodes to access the configured store. This has no effect when 'memory' store is configured. Note that the behaviour how nodes are used is dependent on the library of the configured store. See the Environment Variable Types description for more details." introductionVersion:"1.0.0"`
|
||||
Database string `yaml:"database" env:"ACTIVITYLOG_STORE_DATABASE" desc:"The database name the configured store should use." introductionVersion:"1.0.0"`
|
||||
Table string `yaml:"table" env:"ACTIVITYLOG_STORE_TABLE" desc:"The database table the store should use." introductionVersion:"1.0.0"`
|
||||
TTL time.Duration `yaml:"ttl" env:"OC_PERSISTENT_STORE_TTL;ACTIVITYLOG_STORE_TTL" desc:"Time to live for events in the store. See the Environment Variable Types description for more details." introductionVersion:"1.0.0"`
|
||||
AuthUsername string `yaml:"username" env:"OC_PERSISTENT_STORE_AUTH_USERNAME;ACTIVITYLOG_STORE_AUTH_USERNAME" desc:"The username to authenticate with the store. Only applies when store type 'nats-js-kv' is configured." introductionVersion:"1.0.0"`
|
||||
AuthPassword string `yaml:"password" env:"OC_PERSISTENT_STORE_AUTH_PASSWORD;ACTIVITYLOG_STORE_AUTH_PASSWORD" desc:"The password to authenticate with the store. Only applies when store type 'nats-js-kv' is configured." introductionVersion:"1.0.0"`
|
||||
Store string `yaml:"store" env:"OC_PERSISTENT_STORE;ACTIVITYLOG_STORE" desc:"The type of the store. Supported values are: 'memory', 'nats-js-kv', 'redis-sentinel', 'noop'. See the text description for details." introductionVersion:"1.0.0"`
|
||||
Nodes []string `yaml:"nodes" env:"OC_PERSISTENT_STORE_NODES;ACTIVITYLOG_STORE_NODES" desc:"A list of nodes to access the configured store. This has no effect when 'memory' store is configured. Note that the behaviour how nodes are used is dependent on the library of the configured store. See the Environment Variable Types description for more details." introductionVersion:"1.0.0"`
|
||||
Database string `yaml:"database" env:"ACTIVITYLOG_STORE_DATABASE" desc:"The database name the configured store should use." introductionVersion:"1.0.0"`
|
||||
TTL time.Duration `yaml:"ttl" env:"OC_PERSISTENT_STORE_TTL;ACTIVITYLOG_STORE_TTL" desc:"Time to live for events in the store. See the Environment Variable Types description for more details." introductionVersion:"1.0.0"`
|
||||
AuthUsername string `yaml:"username" env:"OC_PERSISTENT_STORE_AUTH_USERNAME;ACTIVITYLOG_STORE_AUTH_USERNAME" desc:"The username to authenticate with the store. Only applies when store type 'nats-js-kv' is configured." introductionVersion:"1.0.0"`
|
||||
AuthPassword string `yaml:"password" env:"OC_PERSISTENT_STORE_AUTH_PASSWORD;ACTIVITYLOG_STORE_AUTH_PASSWORD" desc:"The password to authenticate with the store. Only applies when store type 'nats-js-kv' is configured." introductionVersion:"1.0.0"`
|
||||
EnableTLS bool `yaml:"enable_tls" env:"OC_PERSISTENT_STORE_ENABLE_TLS;ACTIVITYLOG_STORE_ENABLE_TLS" desc:"Enable TLS for the connection to the store. Only applies when store type 'nats-js-kv' is configured." introductionVersion:"7.3.0"`
|
||||
TLSInsecure bool `yaml:"tls_insecure" env:"OC_INSECURE;OC_PERSISTENT_STORE_TLS_INSECURE;ACTIVITYLOG_STORE_TLS_INSECURE" desc:"Whether to verify the server TLS certificates." introductionVersion:"7.3.0"`
|
||||
TLSRootCACertificate string `yaml:"tls_root_ca_certificate" env:"OC_PERSISTENT_STORE_TLS_ROOT_CA_CERTIFICATE;ACTIVITYLOG_STORE_TLS_ROOT_CA_CERTIFICATE" desc:"The root CA certificate used to validate the server's TLS certificate. If provided ACTIVITYLOG_STORE_TLS_INSECURE will be seen as false." introductionVersion:"7.3.0"`
|
||||
}
|
||||
|
||||
// ServiceAccount is the configuration for the used service account
|
||||
|
||||
Loaded 100 of 2979 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user