import { expect } from 'chai'; import { Network } from '~/src/compose/network'; import { createNetwork, withMockerode } from '~/test-lib/mockerode'; import Docker from 'dockerode'; describe('compose/network: integration tests', () => { const docker = new Docker(); after(async () => { const allNetworks = await docker.listNetworks(); // Delete any remaining networks await Promise.all( allNetworks .filter(({ Name }) => !['bridge', 'host', 'none'].includes(Name)) // exclude docker default network from the cleanup .map(({ Name }) => docker.getNetwork(Name).remove()), ); }); describe('creating and removing networks', () => { // This tests the happy path on the engine, including create and remove it('creates a new network on the engine with the given data', async () => { const network = Network.fromComposeObject('default', 12345, 'deadbeef', { ipam: { driver: 'default', config: [ { subnet: '172.20.0.0/16', ip_range: '172.20.10.0/24', gateway: '172.20.0.1', }, ], options: {}, }, }); // Create the network await network.create(); const dockerNetworkName = Network.generateDockerName( network.appUuid!, network.name, ); // This should not throw const dockerNetwork = await docker .getNetwork(dockerNetworkName) .inspect(); // Check that the create function was called with proper arguments expect(dockerNetwork).to.deep.include({ Name: 'deadbeef_default', Driver: 'bridge', IPAM: { Driver: 'default', Config: [ { Subnet: '172.20.0.0/16', IPRange: '172.20.10.0/24', Gateway: '172.20.0.1', }, ], Options: {}, }, EnableIPv6: false, Internal: false, Labels: { 'io.balena.supervised': 'true', 'io.balena.app-id': '12345', }, Options: {}, ConfigOnly: false, }); // Test network removal await network.remove(); // The network should no longer exist await expect(docker.getNetwork(dockerNetwork).inspect()).to.be.rejected; }); it('throws the error if there is a problem while creating the network', async () => { await withMockerode(async (mockerode) => { const network = Network.fromComposeObject( 'default', 12345, 'deadbeef', { ipam: { driver: 'default', config: [ { subnet: '172.20.0.0/16', ip_range: '172.20.10.0/24', gateway: '172.20.0.1', }, ], options: {}, }, }, ); // Re-define the dockerode.createNetwork to throw mockerode.createNetwork.rejects('Unknown engine error'); // Creating the network should fail return expect(network.create()).to.be.rejected; }); }); }); describe('removing a network', () => { it('removes a legacy network from the engine if it exists', async () => { // Creates a legacy network await docker.createNetwork({ Name: '12345_default' }); // Create a dummy network object const network = Network.fromComposeObject( 'default', 12345, 'deadbeef', {}, ); // Perform the operation await network.remove(); await expect(docker.getNetwork('12345_default').inspect()).to.be.rejected; }); it('ignores the request if the given network does not exist on the engine', async () => { // Create a mock network to add to the mock engine await docker.createNetwork({ Name: 'some_network', }); // Create a dummy network object const network = Network.fromComposeObject( 'default', 12345, 'deadbeef', {}, ); // This should not fail await expect(network.remove()).to.not.be.rejected; // We expect the network state to remain constant await expect(docker.getNetwork('some_network').inspect()).to.not.be .rejected; // Cleanup await docker.getNetwork('some_network').remove(); }); it('throws the error if there is a problem while removing the network', async () => { // Create a mock network to add to the mock engine const mockNetwork = createNetwork({ Id: 'aaaaaaaa', Name: 'a173bdb734884b778f5cc3dffd18733e_default', Labels: { 'io.balena.app-id': '12345', }, }); await withMockerode( async (mockerode) => { // We can change the return value of the mockerode removeNetwork // to have the remove operation fail mockerode.removeNetwork.throws({ statusCode: 500, message: 'Failed to remove the network', }); // Create a dummy network object const network = Network.fromComposeObject( 'default', 12345, 'a173bdb734884b778f5cc3dffd18733e', {}, ); await expect(network.remove()).to.be.rejected; }, { networks: [mockNetwork] }, ); }); }); });