aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--server/tests/api/redundancy/manage-redundancy.ts165
-rw-r--r--server/tests/api/redundancy/redundancy-constraints.ts28
-rw-r--r--server/tests/api/redundancy/redundancy.ts49
-rw-r--r--shared/extra-utils/server/index.ts1
-rw-r--r--shared/extra-utils/server/redundancy-command.ts77
-rw-r--r--shared/extra-utils/server/redundancy.ts88
-rw-r--r--shared/extra-utils/server/servers.ts3
7 files changed, 165 insertions, 246 deletions
diff --git a/server/tests/api/redundancy/manage-redundancy.ts b/server/tests/api/redundancy/manage-redundancy.ts
index 4253124c8..363e4cbfe 100644
--- a/server/tests/api/redundancy/manage-redundancy.ts
+++ b/server/tests/api/redundancy/manage-redundancy.ts
@@ -1,21 +1,21 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ 1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2 2
3import * as chai from 'chai'
4import 'mocha' 3import 'mocha'
4import * as chai from 'chai'
5import { 5import {
6 cleanupTests, 6 cleanupTests,
7 doubleFollow, 7 doubleFollow,
8 flushAndRunMultipleServers, 8 flushAndRunMultipleServers,
9 getLocalIdByUUID, 9 getLocalIdByUUID,
10 RedundancyCommand,
10 ServerInfo, 11 ServerInfo,
11 setAccessTokensToServers, 12 setAccessTokensToServers,
12 uploadVideo, 13 uploadVideo,
13 uploadVideoAndGetId, 14 uploadVideoAndGetId,
15 waitJobs,
14 waitUntilLog 16 waitUntilLog
15} from '../../../../shared/extra-utils' 17} from '@shared/extra-utils'
16import { waitJobs } from '../../../../shared/extra-utils/server/jobs' 18import { VideoPrivacy, VideoRedundanciesTarget } from '@shared/models'
17import { addVideoRedundancy, listVideoRedundancies, removeVideoRedundancy, updateRedundancy } from '@shared/extra-utils/server/redundancy'
18import { VideoPrivacy, VideoRedundanciesTarget, VideoRedundancy } from '@shared/models'
19 19
20const expect = chai.expect 20const expect = chai.expect
21 21
@@ -27,6 +27,8 @@ describe('Test manage videos redundancy', function () {
27 let video2Server2UUID: string 27 let video2Server2UUID: string
28 let redundanciesToRemove: number[] = [] 28 let redundanciesToRemove: number[] = []
29 29
30 let commands: RedundancyCommand[]
31
30 before(async function () { 32 before(async function () {
31 this.timeout(120000) 33 this.timeout(120000)
32 34
@@ -55,6 +57,8 @@ describe('Test manage videos redundancy', function () {
55 // Get the access tokens 57 // Get the access tokens
56 await setAccessTokensToServers(servers) 58 await setAccessTokensToServers(servers)
57 59
60 commands = servers.map(s => s.redundancyCommand)
61
58 { 62 {
59 const res = await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'video 1 server 2' }) 63 const res = await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'video 1 server 2' })
60 video1Server2UUID = res.body.video.uuid 64 video1Server2UUID = res.body.video.uuid
@@ -69,21 +73,17 @@ describe('Test manage videos redundancy', function () {
69 73
70 // Server 1 and server 2 follow each other 74 // Server 1 and server 2 follow each other
71 await doubleFollow(servers[0], servers[1]) 75 await doubleFollow(servers[0], servers[1])
72 await updateRedundancy(servers[0].url, servers[0].accessToken, servers[1].host, true) 76 await commands[0].updateRedundancy({ host: servers[1].host, redundancyAllowed: true })
73 77
74 await waitJobs(servers) 78 await waitJobs(servers)
75 }) 79 })
76 80
77 it('Should not have redundancies on server 3', async function () { 81 it('Should not have redundancies on server 3', async function () {
78 for (const target of targets) { 82 for (const target of targets) {
79 const res = await listVideoRedundancies({ 83 const body = await commands[2].listVideos({ target })
80 url: servers[2].url,
81 accessToken: servers[2].accessToken,
82 target
83 })
84 84
85 expect(res.body.total).to.equal(0) 85 expect(body.total).to.equal(0)
86 expect(res.body.data).to.have.lengthOf(0) 86 expect(body.data).to.have.lengthOf(0)
87 } 87 }
88 }) 88 })
89 89
@@ -94,28 +94,19 @@ describe('Test manage videos redundancy', function () {
94 await waitUntilLog(servers[0], 'Duplicated ', 10) 94 await waitUntilLog(servers[0], 'Duplicated ', 10)
95 await waitJobs(servers) 95 await waitJobs(servers)
96 96
97 const res = await listVideoRedundancies({ 97 const body = await commands[1].listVideos({ target: 'remote-videos' })
98 url: servers[1].url,
99 accessToken: servers[1].accessToken,
100 target: 'remote-videos'
101 })
102 98
103 expect(res.body.total).to.equal(0) 99 expect(body.total).to.equal(0)
104 expect(res.body.data).to.have.lengthOf(0) 100 expect(body.data).to.have.lengthOf(0)
105 }) 101 })
106 102
107 it('Should have "my-videos" redundancies on server 2', async function () { 103 it('Should have "my-videos" redundancies on server 2', async function () {
108 this.timeout(120000) 104 this.timeout(120000)
109 105
110 const res = await listVideoRedundancies({ 106 const body = await commands[1].listVideos({ target: 'my-videos' })
111 url: servers[1].url, 107 expect(body.total).to.equal(2)
112 accessToken: servers[1].accessToken,
113 target: 'my-videos'
114 })
115
116 expect(res.body.total).to.equal(2)
117 108
118 const videos = res.body.data as VideoRedundancy[] 109 const videos = body.data
119 expect(videos).to.have.lengthOf(2) 110 expect(videos).to.have.lengthOf(2)
120 111
121 const videos1 = videos.find(v => v.uuid === video1Server2UUID) 112 const videos1 = videos.find(v => v.uuid === video1Server2UUID)
@@ -139,28 +130,19 @@ describe('Test manage videos redundancy', function () {
139 }) 130 })
140 131
141 it('Should not have "my-videos" redundancies on server 1', async function () { 132 it('Should not have "my-videos" redundancies on server 1', async function () {
142 const res = await listVideoRedundancies({ 133 const body = await commands[0].listVideos({ target: 'my-videos' })
143 url: servers[0].url,
144 accessToken: servers[0].accessToken,
145 target: 'my-videos'
146 })
147 134
148 expect(res.body.total).to.equal(0) 135 expect(body.total).to.equal(0)
149 expect(res.body.data).to.have.lengthOf(0) 136 expect(body.data).to.have.lengthOf(0)
150 }) 137 })
151 138
152 it('Should have "remote-videos" redundancies on server 1', async function () { 139 it('Should have "remote-videos" redundancies on server 1', async function () {
153 this.timeout(120000) 140 this.timeout(120000)
154 141
155 const res = await listVideoRedundancies({ 142 const body = await commands[0].listVideos({ target: 'remote-videos' })
156 url: servers[0].url, 143 expect(body.total).to.equal(2)
157 accessToken: servers[0].accessToken,
158 target: 'remote-videos'
159 })
160 144
161 expect(res.body.total).to.equal(2) 145 const videos = body.data
162
163 const videos = res.body.data as VideoRedundancy[]
164 expect(videos).to.have.lengthOf(2) 146 expect(videos).to.have.lengthOf(2)
165 147
166 const videos1 = videos.find(v => v.uuid === video1Server2UUID) 148 const videos1 = videos.find(v => v.uuid === video1Server2UUID)
@@ -185,47 +167,40 @@ describe('Test manage videos redundancy', function () {
185 167
186 it('Should correctly paginate and sort results', async function () { 168 it('Should correctly paginate and sort results', async function () {
187 { 169 {
188 const res = await listVideoRedundancies({ 170 const body = await commands[0].listVideos({
189 url: servers[0].url,
190 accessToken: servers[0].accessToken,
191 target: 'remote-videos', 171 target: 'remote-videos',
192 sort: 'name', 172 sort: 'name',
193 start: 0, 173 start: 0,
194 count: 2 174 count: 2
195 }) 175 })
196 176
197 const videos = res.body.data 177 const videos = body.data
198 expect(videos[0].name).to.equal('video 1 server 2') 178 expect(videos[0].name).to.equal('video 1 server 2')
199 expect(videos[1].name).to.equal('video 2 server 2') 179 expect(videos[1].name).to.equal('video 2 server 2')
200 } 180 }
201 181
202 { 182 {
203 const res = await listVideoRedundancies({ 183 const body = await commands[0].listVideos({
204 url: servers[0].url,
205 accessToken: servers[0].accessToken,
206 target: 'remote-videos', 184 target: 'remote-videos',
207 sort: '-name', 185 sort: '-name',
208 start: 0, 186 start: 0,
209 count: 2 187 count: 2
210 }) 188 })
211 189
212 const videos = res.body.data 190 const videos = body.data
213 expect(videos[0].name).to.equal('video 2 server 2') 191 expect(videos[0].name).to.equal('video 2 server 2')
214 expect(videos[1].name).to.equal('video 1 server 2') 192 expect(videos[1].name).to.equal('video 1 server 2')
215 } 193 }
216 194
217 { 195 {
218 const res = await listVideoRedundancies({ 196 const body = await commands[0].listVideos({
219 url: servers[0].url,
220 accessToken: servers[0].accessToken,
221 target: 'remote-videos', 197 target: 'remote-videos',
222 sort: '-name', 198 sort: '-name',
223 start: 1, 199 start: 1,
224 count: 1 200 count: 1
225 }) 201 })
226 202
227 const videos = res.body.data 203 expect(body.data[0].name).to.equal('video 1 server 2')
228 expect(videos[0].name).to.equal('video 1 server 2')
229 } 204 }
230 }) 205 })
231 206
@@ -236,30 +211,23 @@ describe('Test manage videos redundancy', function () {
236 await waitJobs(servers) 211 await waitJobs(servers)
237 const videoId = await getLocalIdByUUID(servers[0].url, uuid) 212 const videoId = await getLocalIdByUUID(servers[0].url, uuid)
238 213
239 await addVideoRedundancy({ 214 await commands[0].addVideo({ videoId })
240 url: servers[0].url,
241 accessToken: servers[0].accessToken,
242 videoId
243 })
244 215
245 await waitJobs(servers) 216 await waitJobs(servers)
246 await waitUntilLog(servers[0], 'Duplicated ', 15) 217 await waitUntilLog(servers[0], 'Duplicated ', 15)
247 await waitJobs(servers) 218 await waitJobs(servers)
248 219
249 { 220 {
250 const res = await listVideoRedundancies({ 221 const body = await commands[0].listVideos({
251 url: servers[0].url,
252 accessToken: servers[0].accessToken,
253 target: 'remote-videos', 222 target: 'remote-videos',
254 sort: '-name', 223 sort: '-name',
255 start: 0, 224 start: 0,
256 count: 5 225 count: 5
257 }) 226 })
258 227
259 const videos = res.body.data 228 const video = body.data[0]
260 expect(videos[0].name).to.equal('video 3 server 2')
261 229
262 const video = videos[0] 230 expect(video.name).to.equal('video 3 server 2')
263 expect(video.redundancies.files).to.have.lengthOf(4) 231 expect(video.redundancies.files).to.have.lengthOf(4)
264 expect(video.redundancies.streamingPlaylists).to.have.lengthOf(1) 232 expect(video.redundancies.streamingPlaylists).to.have.lengthOf(1)
265 233
@@ -276,19 +244,15 @@ describe('Test manage videos redundancy', function () {
276 } 244 }
277 } 245 }
278 246
279 const res = await listVideoRedundancies({ 247 const body = await commands[1].listVideos({
280 url: servers[1].url,
281 accessToken: servers[1].accessToken,
282 target: 'my-videos', 248 target: 'my-videos',
283 sort: '-name', 249 sort: '-name',
284 start: 0, 250 start: 0,
285 count: 5 251 count: 5
286 }) 252 })
287 253
288 const videos = res.body.data 254 const video = body.data[0]
289 expect(videos[0].name).to.equal('video 3 server 2') 255 expect(video.name).to.equal('video 3 server 2')
290
291 const video = videos[0]
292 expect(video.redundancies.files).to.have.lengthOf(4) 256 expect(video.redundancies.files).to.have.lengthOf(4)
293 expect(video.redundancies.streamingPlaylists).to.have.lengthOf(1) 257 expect(video.redundancies.streamingPlaylists).to.have.lengthOf(1)
294 258
@@ -307,64 +271,47 @@ describe('Test manage videos redundancy', function () {
307 this.timeout(120000) 271 this.timeout(120000)
308 272
309 for (const redundancyId of redundanciesToRemove) { 273 for (const redundancyId of redundanciesToRemove) {
310 await removeVideoRedundancy({ 274 await commands[0].removeVideo({ redundancyId })
311 url: servers[0].url,
312 accessToken: servers[0].accessToken,
313 redundancyId
314 })
315 } 275 }
316 276
317 { 277 {
318 const res = await listVideoRedundancies({ 278 const body = await commands[0].listVideos({
319 url: servers[0].url,
320 accessToken: servers[0].accessToken,
321 target: 'remote-videos', 279 target: 'remote-videos',
322 sort: '-name', 280 sort: '-name',
323 start: 0, 281 start: 0,
324 count: 5 282 count: 5
325 }) 283 })
326 284
327 const videos = res.body.data 285 const videos = body.data
328 expect(videos).to.have.lengthOf(2)
329 286
330 expect(videos[0].name).to.equal('video 2 server 2') 287 expect(videos).to.have.lengthOf(2)
331 288
332 redundanciesToRemove = []
333 const video = videos[0] 289 const video = videos[0]
290 expect(video.name).to.equal('video 2 server 2')
334 expect(video.redundancies.files).to.have.lengthOf(4) 291 expect(video.redundancies.files).to.have.lengthOf(4)
335 expect(video.redundancies.streamingPlaylists).to.have.lengthOf(1) 292 expect(video.redundancies.streamingPlaylists).to.have.lengthOf(1)
336 293
337 const redundancies = video.redundancies.files.concat(video.redundancies.streamingPlaylists) 294 const redundancies = video.redundancies.files.concat(video.redundancies.streamingPlaylists)
338 295
339 for (const r of redundancies) { 296 redundanciesToRemove = redundancies.map(r => r.id)
340 redundanciesToRemove.push(r.id)
341 }
342 } 297 }
343 }) 298 })
344 299
345 it('Should remove another (auto) redundancy', async function () { 300 it('Should remove another (auto) redundancy', async function () {
346 { 301 for (const redundancyId of redundanciesToRemove) {
347 for (const redundancyId of redundanciesToRemove) { 302 await commands[0].removeVideo({ redundancyId })
348 await removeVideoRedundancy({ 303 }
349 url: servers[0].url,
350 accessToken: servers[0].accessToken,
351 redundancyId
352 })
353 }
354 304
355 const res = await listVideoRedundancies({ 305 const body = await commands[0].listVideos({
356 url: servers[0].url, 306 target: 'remote-videos',
357 accessToken: servers[0].accessToken, 307 sort: '-name',
358 target: 'remote-videos', 308 start: 0,
359 sort: '-name', 309 count: 5
360 start: 0, 310 })
361 count: 5
362 })
363 311
364 const videos = res.body.data 312 const videos = body.data
365 expect(videos[0].name).to.equal('video 1 server 2') 313 expect(videos).to.have.lengthOf(1)
366 expect(videos).to.have.lengthOf(1) 314 expect(videos[0].name).to.equal('video 1 server 2')
367 }
368 }) 315 })
369 316
370 after(async function () { 317 after(async function () {
diff --git a/server/tests/api/redundancy/redundancy-constraints.ts b/server/tests/api/redundancy/redundancy-constraints.ts
index 602f4bc1b..a666976b3 100644
--- a/server/tests/api/redundancy/redundancy-constraints.ts
+++ b/server/tests/api/redundancy/redundancy-constraints.ts
@@ -1,9 +1,6 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ 1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2 2
3import 'mocha' 3import 'mocha'
4import * as chai from 'chai'
5import { listVideoRedundancies, updateRedundancy } from '@shared/extra-utils/server/redundancy'
6import { VideoPrivacy } from '@shared/models'
7import { 4import {
8 cleanupTests, 5 cleanupTests,
9 flushAndRunServer, 6 flushAndRunServer,
@@ -13,9 +10,10 @@ import {
13 setAccessTokensToServers, 10 setAccessTokensToServers,
14 updateVideo, 11 updateVideo,
15 uploadVideo, 12 uploadVideo,
13 waitJobs,
16 waitUntilLog 14 waitUntilLog
17} from '../../../../shared/extra-utils' 15} from '@shared/extra-utils'
18import { waitJobs } from '../../../../shared/extra-utils/server/jobs' 16import { VideoPrivacy } from '@shared/models'
19 17
20const expect = chai.expect 18const expect = chai.expect
21 19
@@ -50,23 +48,15 @@ describe('Test redundancy constraints', function () {
50 } 48 }
51 49
52 async function getTotalRedundanciesLocalServer () { 50 async function getTotalRedundanciesLocalServer () {
53 const res = await listVideoRedundancies({ 51 const body = await localServer.redundancyCommand.listVideos({ target: 'my-videos' })
54 url: localServer.url,
55 accessToken: localServer.accessToken,
56 target: 'my-videos'
57 })
58 52
59 return res.body.total 53 return body.total
60 } 54 }
61 55
62 async function getTotalRedundanciesRemoteServer () { 56 async function getTotalRedundanciesRemoteServer () {
63 const res = await listVideoRedundancies({ 57 const body = await remoteServer.redundancyCommand.listVideos({ target: 'remote-videos' })
64 url: remoteServer.url,
65 accessToken: remoteServer.accessToken,
66 target: 'remote-videos'
67 })
68 58
69 return res.body.total 59 return body.total
70 } 60 }
71 61
72 before(async function () { 62 before(async function () {
@@ -99,7 +89,7 @@ describe('Test redundancy constraints', function () {
99 // Server 1 and server 2 follow each other 89 // Server 1 and server 2 follow each other
100 await remoteServer.followsCommand.follow({ targets: [ localServer.url ] }) 90 await remoteServer.followsCommand.follow({ targets: [ localServer.url ] })
101 await waitJobs(servers) 91 await waitJobs(servers)
102 await updateRedundancy(remoteServer.url, remoteServer.accessToken, localServer.host, true) 92 await remoteServer.redundancyCommand.updateRedundancy({ host: localServer.host, redundancyAllowed: true })
103 93
104 await waitJobs(servers) 94 await waitJobs(servers)
105 }) 95 })
@@ -161,7 +151,7 @@ describe('Test redundancy constraints', function () {
161 } 151 }
162 } 152 }
163 } 153 }
164 await killallServers([ localServer ]) 154 killallServers([ localServer ])
165 await reRunServer(localServer, config) 155 await reRunServer(localServer, config)
166 156
167 await uploadWrapper('video 3 server 2') 157 await uploadWrapper('video 3 server 2')
diff --git a/server/tests/api/redundancy/redundancy.ts b/server/tests/api/redundancy/redundancy.ts
index dfe8099ed..5b970473c 100644
--- a/server/tests/api/redundancy/redundancy.ts
+++ b/server/tests/api/redundancy/redundancy.ts
@@ -5,7 +5,8 @@ import * as chai from 'chai'
5import { readdir } from 'fs-extra' 5import { readdir } from 'fs-extra'
6import * as magnetUtil from 'magnet-uri' 6import * as magnetUtil from 'magnet-uri'
7import { join } from 'path' 7import { join } from 'path'
8import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' 8import { removeVideoRedundancy } from '@server/lib/redundancy'
9import { HttpStatusCode } from '@shared/core-utils'
9import { 10import {
10 checkSegmentHash, 11 checkSegmentHash,
11 checkVideoFilesWereRemoved, 12 checkVideoFilesWereRemoved,
@@ -26,19 +27,18 @@ import {
26 uploadVideo, 27 uploadVideo,
27 viewVideo, 28 viewVideo,
28 wait, 29 wait,
30 waitJobs,
29 waitUntilLog 31 waitUntilLog
30} from '../../../../shared/extra-utils' 32} from '@shared/extra-utils'
31import { waitJobs } from '../../../../shared/extra-utils/server/jobs' 33import { getStats } from '@shared/extra-utils/server/stats'
32import { 34import {
33 addVideoRedundancy, 35 ServerStats,
34 listVideoRedundancies, 36 VideoDetails,
35 removeVideoRedundancy, 37 VideoPrivacy,
36 updateRedundancy 38 VideoRedundancy,
37} from '../../../../shared/extra-utils/server/redundancy' 39 VideoRedundancyStrategy,
38import { getStats } from '../../../../shared/extra-utils/server/stats' 40 VideoRedundancyStrategyWithManual
39import { VideoRedundancy, VideoRedundancyStrategy, VideoRedundancyStrategyWithManual } from '../../../../shared/models/redundancy' 41} from '@shared/models'
40import { ServerStats } from '../../../../shared/models/server/server-stats.model'
41import { VideoDetails, VideoPrivacy } from '../../../../shared/models/videos'
42 42
43const expect = chai.expect 43const expect = chai.expect
44 44
@@ -279,7 +279,7 @@ async function findServerFollows () {
279} 279}
280 280
281async function enableRedundancyOnServer1 () { 281async function enableRedundancyOnServer1 () {
282 await updateRedundancy(servers[0].url, servers[0].accessToken, servers[1].host, true) 282 await servers[0].redundancyCommand.updateRedundancy({ host: servers[1].host, redundancyAllowed: true })
283 283
284 const { server2, server3 } = await findServerFollows() 284 const { server2, server3 } = await findServerFollows()
285 285
@@ -291,7 +291,7 @@ async function enableRedundancyOnServer1 () {
291} 291}
292 292
293async function disableRedundancyOnServer1 () { 293async function disableRedundancyOnServer1 () {
294 await updateRedundancy(servers[0].url, servers[0].accessToken, servers[1].host, false) 294 await servers[0].redundancyCommand.updateRedundancy({ host: servers[1].host, redundancyAllowed: false })
295 295
296 const { server2, server3 } = await findServerFollows() 296 const { server2, server3 } = await findServerFollows()
297 297
@@ -551,11 +551,7 @@ describe('Test videos redundancy', function () {
551 }) 551 })
552 552
553 it('Should create a redundancy on first video', async function () { 553 it('Should create a redundancy on first video', async function () {
554 await addVideoRedundancy({ 554 await servers[0].redundancyCommand.addVideo({ videoId: video1Server2Id })
555 url: servers[0].url,
556 accessToken: servers[0].accessToken,
557 videoId: video1Server2Id
558 })
559 }) 555 })
560 556
561 it('Should have 2 webseeds on the first video', async function () { 557 it('Should have 2 webseeds on the first video', async function () {
@@ -573,22 +569,15 @@ describe('Test videos redundancy', function () {
573 it('Should manually remove redundancies on server 1 and remove duplicated videos', async function () { 569 it('Should manually remove redundancies on server 1 and remove duplicated videos', async function () {
574 this.timeout(80000) 570 this.timeout(80000)
575 571
576 const res = await listVideoRedundancies({ 572 const body = await servers[0].redundancyCommand.listVideos({ target: 'remote-videos' })
577 url: servers[0].url,
578 accessToken: servers[0].accessToken,
579 target: 'remote-videos'
580 })
581 573
582 const videos = res.body.data as VideoRedundancy[] 574 const videos = body.data
583 expect(videos).to.have.lengthOf(1) 575 expect(videos).to.have.lengthOf(1)
584 576
585 const video = videos[0] 577 const video = videos[0]
578
586 for (const r of video.redundancies.files.concat(video.redundancies.streamingPlaylists)) { 579 for (const r of video.redundancies.files.concat(video.redundancies.streamingPlaylists)) {
587 await removeVideoRedundancy({ 580 await servers[0].redundancyCommand.removeVideo({ redundancyId: r.id })
588 url: servers[0].url,
589 accessToken: servers[0].accessToken,
590 redundancyId: r.id
591 })
592 } 581 }
593 582
594 await waitJobs(servers) 583 await waitJobs(servers)
diff --git a/shared/extra-utils/server/index.ts b/shared/extra-utils/server/index.ts
index e602fec7e..3ee70f0cf 100644
--- a/shared/extra-utils/server/index.ts
+++ b/shared/extra-utils/server/index.ts
@@ -6,3 +6,4 @@ export * from './jobs'
6export * from './jobs-command' 6export * from './jobs-command'
7export * from './plugins-command' 7export * from './plugins-command'
8export * from './plugins' 8export * from './plugins'
9export * from './redundancy-command'
diff --git a/shared/extra-utils/server/redundancy-command.ts b/shared/extra-utils/server/redundancy-command.ts
new file mode 100644
index 000000000..d717d35f8
--- /dev/null
+++ b/shared/extra-utils/server/redundancy-command.ts
@@ -0,0 +1,77 @@
1import { ResultList, VideoRedundanciesTarget, VideoRedundancy } from '@shared/models'
2import { HttpStatusCode } from '../../core-utils/miscs/http-error-codes'
3import { AbstractCommand, OverrideCommandOptions } from '../shared'
4
5export class RedundancyCommand extends AbstractCommand {
6
7 updateRedundancy (options: OverrideCommandOptions & {
8 host: string
9 redundancyAllowed: boolean
10 }) {
11 const { host, redundancyAllowed } = options
12 const path = '/api/v1/server/redundancy/' + host
13
14 return this.putBodyRequest({
15 ...options,
16
17 path,
18 fields: { redundancyAllowed },
19 defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
20 })
21 }
22
23 listVideos (options: OverrideCommandOptions & {
24 target: VideoRedundanciesTarget
25 start?: number
26 count?: number
27 sort?: string
28 }) {
29 const path = '/api/v1/server/redundancy/videos'
30
31 const { target, start, count, sort } = options
32
33 return this.getRequestBody<ResultList<VideoRedundancy>>({
34 ...options,
35
36 path,
37
38 query: {
39 start: start ?? 0,
40 count: count ?? 5,
41 sort: sort ?? 'name',
42 target
43 },
44
45 defaultExpectedStatus: HttpStatusCode.OK_200
46 })
47 }
48
49 addVideo (options: OverrideCommandOptions & {
50 videoId: number
51 }) {
52 const path = '/api/v1/server/redundancy/videos'
53 const { videoId } = options
54
55 return this.postBodyRequest({
56 ...options,
57
58 path,
59 fields: { videoId },
60 defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
61 })
62 }
63
64 removeVideo (options: OverrideCommandOptions & {
65 redundancyId: number
66 }) {
67 const { redundancyId } = options
68 const path = '/api/v1/server/redundancy/videos/' + redundancyId
69
70 return this.deleteRequest({
71 ...options,
72
73 path,
74 defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
75 })
76 }
77}
diff --git a/shared/extra-utils/server/redundancy.ts b/shared/extra-utils/server/redundancy.ts
deleted file mode 100644
index b83815a37..000000000
--- a/shared/extra-utils/server/redundancy.ts
+++ /dev/null
@@ -1,88 +0,0 @@
1import { makeDeleteRequest, makeGetRequest, makePostBodyRequest, makePutBodyRequest } from '../requests/requests'
2import { VideoRedundanciesTarget } from '@shared/models'
3import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
4
5function updateRedundancy (
6 url: string,
7 accessToken: string,
8 host: string,
9 redundancyAllowed: boolean,
10 expectedStatus = HttpStatusCode.NO_CONTENT_204
11) {
12 const path = '/api/v1/server/redundancy/' + host
13
14 return makePutBodyRequest({
15 url,
16 path,
17 token: accessToken,
18 fields: { redundancyAllowed },
19 statusCodeExpected: expectedStatus
20 })
21}
22
23function listVideoRedundancies (options: {
24 url: string
25 accessToken: string
26 target: VideoRedundanciesTarget
27 start?: number
28 count?: number
29 sort?: string
30 statusCodeExpected?: HttpStatusCode
31}) {
32 const path = '/api/v1/server/redundancy/videos'
33
34 const { url, accessToken, target, statusCodeExpected, start, count, sort } = options
35
36 return makeGetRequest({
37 url,
38 token: accessToken,
39 path,
40 query: {
41 start: start ?? 0,
42 count: count ?? 5,
43 sort: sort ?? 'name',
44 target
45 },
46 statusCodeExpected: statusCodeExpected || HttpStatusCode.OK_200
47 })
48}
49
50function addVideoRedundancy (options: {
51 url: string
52 accessToken: string
53 videoId: number
54}) {
55 const path = '/api/v1/server/redundancy/videos'
56 const { url, accessToken, videoId } = options
57
58 return makePostBodyRequest({
59 url,
60 token: accessToken,
61 path,
62 fields: { videoId },
63 statusCodeExpected: HttpStatusCode.NO_CONTENT_204
64 })
65}
66
67function removeVideoRedundancy (options: {
68 url: string
69 accessToken: string
70 redundancyId: number
71}) {
72 const { url, accessToken, redundancyId } = options
73 const path = '/api/v1/server/redundancy/videos/' + redundancyId
74
75 return makeDeleteRequest({
76 url,
77 token: accessToken,
78 path,
79 statusCodeExpected: HttpStatusCode.NO_CONTENT_204
80 })
81}
82
83export {
84 updateRedundancy,
85 listVideoRedundancies,
86 addVideoRedundancy,
87 removeVideoRedundancy
88}
diff --git a/shared/extra-utils/server/servers.ts b/shared/extra-utils/server/servers.ts
index 79d6b7b1a..eaf39ecea 100644
--- a/shared/extra-utils/server/servers.ts
+++ b/shared/extra-utils/server/servers.ts
@@ -21,6 +21,7 @@ import { DebugCommand } from './debug-command'
21import { FollowsCommand } from './follows-command' 21import { FollowsCommand } from './follows-command'
22import { JobsCommand } from './jobs-command' 22import { JobsCommand } from './jobs-command'
23import { PluginsCommand } from './plugins-command' 23import { PluginsCommand } from './plugins-command'
24import { RedundancyCommand } from './redundancy-command'
24 25
25interface ServerInfo { 26interface ServerInfo {
26 app: ChildProcess 27 app: ChildProcess
@@ -87,6 +88,7 @@ interface ServerInfo {
87 followsCommand?: FollowsCommand 88 followsCommand?: FollowsCommand
88 jobsCommand?: JobsCommand 89 jobsCommand?: JobsCommand
89 pluginsCommand?: PluginsCommand 90 pluginsCommand?: PluginsCommand
91 redundancyCommand?: RedundancyCommand
90} 92}
91 93
92function parallelTests () { 94function parallelTests () {
@@ -305,6 +307,7 @@ async function runServer (server: ServerInfo, configOverrideArg?: any, args = []
305 server.followsCommand = new FollowsCommand(server) 307 server.followsCommand = new FollowsCommand(server)
306 server.jobsCommand = new JobsCommand(server) 308 server.jobsCommand = new JobsCommand(server)
307 server.pluginsCommand = new PluginsCommand(server) 309 server.pluginsCommand = new PluginsCommand(server)
310 server.redundancyCommand = new RedundancyCommand(server)
308 311
309 res(server) 312 res(server)
310 }) 313 })