mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	feat: Remove applications (#635)
This commit is contained in:
		
							parent
							
								
									edf6d70116
								
							
						
					
					
						commit
						4a3c136167
					
				| @ -87,6 +87,12 @@ class ClientApplicationsDb { | ||||
|         return mapRow(row); | ||||
|     } | ||||
| 
 | ||||
|     async deleteApplication(appName) { | ||||
|         return this.db(TABLE) | ||||
|             .where('app_name', appName) | ||||
|             .del(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Could also be done in SQL: | ||||
|      * (not sure if it is faster though) | ||||
|  | ||||
| @ -127,6 +127,12 @@ class ClientInstanceStore { | ||||
| 
 | ||||
|         return rows.map(mapRow); | ||||
|     } | ||||
| 
 | ||||
|     async deleteForApplication(appName) { | ||||
|         return this.db(TABLE) | ||||
|             .where('app_name', appName) | ||||
|             .del(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| module.exports = ClientInstanceStore; | ||||
|  | ||||
| @ -32,6 +32,11 @@ class MetricsController extends Controller { | ||||
|             this.createApplication, | ||||
|             UPDATE_APPLICATION, | ||||
|         ); | ||||
|         this.delete( | ||||
|             '/applications/:appName', | ||||
|             this.deleteApplication, | ||||
|             UPDATE_APPLICATION, | ||||
|         ); | ||||
|         this.get('/applications/', this.getApplications); | ||||
|         this.get('/applications/:appName', this.getApplication); | ||||
|     } | ||||
| @ -76,6 +81,27 @@ class MetricsController extends Controller { | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     async deleteApplication(req, res) { | ||||
|         const { appName } = req.params; | ||||
| 
 | ||||
|         try { | ||||
|             await this.clientApplicationsStore.getApplication(appName); | ||||
|         } catch (e) { | ||||
|             this.logger.error(e); | ||||
|             res.status(409).end(); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         try { | ||||
|             await this.clientInstanceStore.deleteForApplication(appName); | ||||
|             await this.clientApplicationsStore.deleteApplication(appName); | ||||
|             res.status(200).end(); | ||||
|         } catch (e) { | ||||
|             this.logger.error(e); | ||||
|             res.status(500).end(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     async createApplication(req, res) { | ||||
|         const input = { ...req.body, appName: req.params.appName }; | ||||
|         const { value: applicationData, error } = schema.validate(input); | ||||
|  | ||||
| @ -154,3 +154,27 @@ test('should store application details wihtout strategies', t => { | ||||
|         .send({ appName, url: 'htto://asd.com' }) | ||||
|         .expect(202); | ||||
| }); | ||||
| 
 | ||||
| test('should not delete unknown application', t => { | ||||
|     t.plan(0); | ||||
|     const { request, perms } = getSetup(); | ||||
|     const appName = 'unknown'; | ||||
|     perms.withPermissions(UPDATE_APPLICATION); | ||||
| 
 | ||||
|     return request | ||||
|         .delete(`/api/admin/metrics/applications/${appName}`) | ||||
|         .expect(409); | ||||
| }); | ||||
| 
 | ||||
| test('should delete application', t => { | ||||
|     t.plan(0); | ||||
|     const { request, stores, perms } = getSetup(); | ||||
|     const appName = 'deletable-test'; | ||||
| 
 | ||||
|     perms.withPermissions(UPDATE_APPLICATION); | ||||
|     stores.clientApplicationsStore.upsert({ appName }); | ||||
| 
 | ||||
|     return request | ||||
|         .delete(`/api/admin/metrics/applications/${appName}`) | ||||
|         .expect(200); | ||||
| }); | ||||
|  | ||||
| @ -22,61 +22,6 @@ test.afterEach(async () => { | ||||
|     await reset(); | ||||
| }); | ||||
| 
 | ||||
| test.serial('should register client', async t => { | ||||
|     t.plan(0); | ||||
|     const request = await setupApp(stores); | ||||
|     return request | ||||
|         .post('/api/client/register') | ||||
|         .send({ | ||||
|             appName: 'demo', | ||||
|             instanceId: 'test', | ||||
|             strategies: ['default'], | ||||
|             started: Date.now(), | ||||
|             interval: 10, | ||||
|         }) | ||||
|         .expect(202); | ||||
| }); | ||||
| 
 | ||||
| test.serial('should allow client to register multiple times', async t => { | ||||
|     t.plan(0); | ||||
|     const request = await setupApp(stores); | ||||
|     const clientRegistration = { | ||||
|         appName: 'multipleRegistration', | ||||
|         instanceId: 'test', | ||||
|         strategies: ['default', 'another'], | ||||
|         started: Date.now(), | ||||
|         interval: 10, | ||||
|     }; | ||||
| 
 | ||||
|     return request | ||||
|         .post('/api/client/register') | ||||
|         .send(clientRegistration) | ||||
|         .expect(202) | ||||
|         .then(() => | ||||
|             request | ||||
|                 .post('/api/client/register') | ||||
|                 .send(clientRegistration) | ||||
|                 .expect(202), | ||||
|         ); | ||||
| }); | ||||
| 
 | ||||
| test.serial('should accept client metrics', async t => { | ||||
|     t.plan(0); | ||||
|     const request = await setupApp(stores); | ||||
|     return request | ||||
|         .post('/api/client/metrics') | ||||
|         .send({ | ||||
|             appName: 'demo', | ||||
|             instanceId: '1', | ||||
|             bucket: { | ||||
|                 start: Date.now(), | ||||
|                 stop: Date.now(), | ||||
|                 toggles: {}, | ||||
|             }, | ||||
|         }) | ||||
|         .expect(202); | ||||
| }); | ||||
| 
 | ||||
| test.serial('should get application details', async t => { | ||||
|     t.plan(3); | ||||
|     const request = await setupApp(stores); | ||||
| @ -98,6 +43,32 @@ test.serial('should get list of applications', async t => { | ||||
|         .expect('Content-Type', /json/) | ||||
|         .expect(res => { | ||||
|             t.true(res.status === 200); | ||||
|             t.is(res.body.applications.length, 3); | ||||
|         }); | ||||
| }); | ||||
| 
 | ||||
| test.serial('should delete application', async t => { | ||||
|     t.plan(2); | ||||
|     const request = await setupApp(stores); | ||||
|     await request | ||||
|         .delete('/api/admin/metrics/applications/deletable-app') | ||||
|         .expect(res => { | ||||
|             t.is(res.status, 200); | ||||
|         }); | ||||
|     return request | ||||
|         .get('/api/admin/metrics/applications') | ||||
|         .expect('Content-Type', /json/) | ||||
|         .expect(res => { | ||||
|             t.is(res.body.applications.length, 2); | ||||
|         }); | ||||
| }); | ||||
| 
 | ||||
| test.serial('should get 409 when deleting unknwn application', async t => { | ||||
|     t.plan(1); | ||||
|     const request = await setupApp(stores); | ||||
|     return request | ||||
|         .delete('/api/admin/metrics/applications/unkown') | ||||
|         .expect(res => { | ||||
|             t.is(res.status, 409); | ||||
|         }); | ||||
| }); | ||||
|  | ||||
| @ -37,3 +37,58 @@ test.serial('should require valid send metrics', async t => { | ||||
|         }) | ||||
|         .expect(400); | ||||
| }); | ||||
| 
 | ||||
| test.serial('should register client', async t => { | ||||
|     t.plan(0); | ||||
|     const request = await setupApp(stores); | ||||
|     return request | ||||
|         .post('/api/client/register') | ||||
|         .send({ | ||||
|             appName: 'demo', | ||||
|             instanceId: 'test', | ||||
|             strategies: ['default'], | ||||
|             started: Date.now(), | ||||
|             interval: 10, | ||||
|         }) | ||||
|         .expect(202); | ||||
| }); | ||||
| 
 | ||||
| test.serial('should allow client to register multiple times', async t => { | ||||
|     t.plan(0); | ||||
|     const request = await setupApp(stores); | ||||
|     const clientRegistration = { | ||||
|         appName: 'multipleRegistration', | ||||
|         instanceId: 'test', | ||||
|         strategies: ['default', 'another'], | ||||
|         started: Date.now(), | ||||
|         interval: 10, | ||||
|     }; | ||||
| 
 | ||||
|     return request | ||||
|         .post('/api/client/register') | ||||
|         .send(clientRegistration) | ||||
|         .expect(202) | ||||
|         .then(() => | ||||
|             request | ||||
|                 .post('/api/client/register') | ||||
|                 .send(clientRegistration) | ||||
|                 .expect(202), | ||||
|         ); | ||||
| }); | ||||
| 
 | ||||
| test.serial('should accept client metrics', async t => { | ||||
|     t.plan(0); | ||||
|     const request = await setupApp(stores); | ||||
|     return request | ||||
|         .post('/api/client/metrics') | ||||
|         .send({ | ||||
|             appName: 'demo', | ||||
|             instanceId: '1', | ||||
|             bucket: { | ||||
|                 start: Date.now(), | ||||
|                 stop: Date.now(), | ||||
|                 toggles: {}, | ||||
|             }, | ||||
|         }) | ||||
|         .expect(202); | ||||
| }); | ||||
|  | ||||
| @ -30,6 +30,11 @@ | ||||
|       "appName": "demo-app-2", | ||||
|       "strategies": ["default", "extra"], | ||||
|       "description": "hello" | ||||
|     }, | ||||
|     { | ||||
|       "appName": "deletable-app", | ||||
|       "strategies": ["default"], | ||||
|       "description": "Some desc" | ||||
|     } | ||||
|   ], | ||||
|   "clientInstances": [ | ||||
| @ -46,6 +51,13 @@ | ||||
|       "strategies": ["default"], | ||||
|       "started": 1516026938494, | ||||
|       "interval": 10 | ||||
|     }, | ||||
|     { | ||||
|       "appName": "deletable-app", | ||||
|       "instanceId": "inst-1", | ||||
|       "strategies": ["default"], | ||||
|       "started": 1516026938494, | ||||
|       "interval": 10 | ||||
|     } | ||||
|   ], | ||||
|   "features": [ | ||||
|  | ||||
							
								
								
									
										13
									
								
								test/fixtures/fake-client-applications-store.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										13
									
								
								test/fixtures/fake-client-applications-store.js
									
									
									
									
										vendored
									
									
								
							| @ -1,7 +1,7 @@ | ||||
| 'use strict'; | ||||
| 
 | ||||
| module.exports = () => { | ||||
|     const apps = []; | ||||
|     let apps = []; | ||||
| 
 | ||||
|     return { | ||||
|         upsert: app => { | ||||
| @ -9,6 +9,15 @@ module.exports = () => { | ||||
|             return Promise.resolve(); | ||||
|         }, | ||||
|         getApplications: () => Promise.resolve(apps), | ||||
|         getApplication: appName => apps.filter(a => a.name === appName)[0], | ||||
|         getApplication: appName => { | ||||
|             const app = apps.filter(a => a.appName === appName)[0]; | ||||
|             if (!app) { | ||||
|                 throw new Error(`Could not find app=${appName}`); | ||||
|             } | ||||
|             return app; | ||||
|         }, | ||||
|         deleteApplication: appName => { | ||||
|             apps = apps.filter(app => app.appName !== appName); | ||||
|         }, | ||||
|     }; | ||||
| }; | ||||
|  | ||||
							
								
								
									
										1
									
								
								test/fixtures/fake-client-instance-store.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								test/fixtures/fake-client-instance-store.js
									
									
									
									
										vendored
									
									
								
							| @ -3,4 +3,5 @@ | ||||
| module.exports = () => ({ | ||||
|     insert: () => Promise.resolve(), | ||||
|     getApplications: () => Promise.resolve([]), | ||||
|     deleteForApplication: () => Promise.resolve(), | ||||
| }); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user