diff --git a/components/console/src/pages/Backbones/BackboneDetail.jsx b/components/console/src/pages/Backbones/BackboneDetail.jsx index b8c25891..942309ac 100644 --- a/components/console/src/pages/Backbones/BackboneDetail.jsx +++ b/components/console/src/pages/Backbones/BackboneDetail.jsx @@ -38,7 +38,6 @@ const BackboneDetail = () => { return () => { CancelWatch(watchContext); }; - // eslint-disable-next-line react-hooks/exhaustive-deps }, [backboneId]); return ( @@ -83,7 +82,6 @@ const BackboneDetail = () => { {!loading && !error && viewMode === 'list' && ( diff --git a/components/console/src/pages/Backbones/BackboneListView.jsx b/components/console/src/pages/Backbones/BackboneListView.jsx index fe087bc3..f2191d41 100644 --- a/components/console/src/pages/Backbones/BackboneListView.jsx +++ b/components/console/src/pages/Backbones/BackboneListView.jsx @@ -26,7 +26,6 @@ import SiteDeployment from './SiteDeployment'; const BackboneListView = ({ sites, - backboneName, backboneId, backboneOwnerGroup = '', }) => { @@ -515,4 +514,4 @@ const BackboneListView = ({ export default BackboneListView; -// Made with Bob \ No newline at end of file +// Made with Bob diff --git a/components/console/src/pages/Backbones/SiteDetail.jsx b/components/console/src/pages/Backbones/SiteDetail.jsx index 3bb79aa5..ba11326e 100644 --- a/components/console/src/pages/Backbones/SiteDetail.jsx +++ b/components/console/src/pages/Backbones/SiteDetail.jsx @@ -260,7 +260,7 @@ const SiteDetail = () => { if (errorBody) { errorMessage = errorBody; } - } catch (e) { + } catch { // If we can't read the body, use the default error message } throw new Error(errorMessage); @@ -311,7 +311,7 @@ const SiteDetail = () => { if (errorBody) { errorMessage = errorBody; } - } catch (e) { + } catch { // If we can't read the body, use the default error message } throw new Error(errorMessage); @@ -385,7 +385,7 @@ const SiteDetail = () => { if (errorBody) { errorMessage = errorBody; } - } catch (e) { + } catch { // If we can't read the body, use the default error message } throw new Error(errorMessage); @@ -464,8 +464,6 @@ const SiteDetail = () => { case 'error': type = 'red'; break; - default: - type = 'gray'; } return { text: lifecycle, @@ -1024,4 +1022,4 @@ const SiteDetail = () => { export default SiteDetail; -// Made with Bob \ No newline at end of file +// Made with Bob diff --git a/components/console/src/pages/VANs/VANs.jsx b/components/console/src/pages/VANs/VANs.jsx index e0655e51..5fea6d49 100644 --- a/components/console/src/pages/VANs/VANs.jsx +++ b/components/console/src/pages/VANs/VANs.jsx @@ -172,7 +172,7 @@ const VANs = () => { if (errorBody) { errorMessage = errorBody; } - } catch (e) { + } catch { // If we can't read the body, use the default error message } throw new Error(errorMessage); @@ -211,7 +211,7 @@ const VANs = () => { setExposeNetworkObserver(false); // Fetch access points of type "van" from the VAN's backbone - let backbone = (van.backbone) ? van.backbone : selectedBackbone; + const backbone = (van.backbone) ? van.backbone : selectedBackbone; if (backbone) { try { setLoadingAccessPoints(true); diff --git a/components/management-controller/src/api-admin.js b/components/management-controller/src/api-admin.js index 885e2ff6..531a1299 100644 --- a/components/management-controller/src/api-admin.js +++ b/components/management-controller/src/api-admin.js @@ -34,7 +34,7 @@ const createBackbone = async function(req, res) { let returnStatus; const form = new IncomingForm(); try { - const [fields, files] = await form.parse(req); + const [fields] = await form.parse(req); const norm = ValidateAndNormalizeFields(fields, { 'name' : {type: 'dns-segment', optional: false}, 'ownerGroup': {type: 'string', optional: true, default: ''}, @@ -44,7 +44,6 @@ const createBackbone = async function(req, res) { const notify = new NotifyTransaction(); try { let backboneId; - let siteId; await queryWithContext(req, client, async (client, userInfo) => { const result = await client.query( "INSERT INTO Backbones(Name, LifeCycle, Owner, OwnerGroup, CoLocatedNamespace) " + @@ -79,7 +78,7 @@ const createBackboneSite = async function(req, res) { throw new Error('Backbone-Id is not a valid uuid'); } - const [fields, files] = await form.parse(req) + const [fields] = await form.parse(req) const norm = ValidateAndNormalizeFields(fields, { 'name' : {type: 'dnsname', optional: false}, 'platform' : {type: 'dnsname', optional: false}, @@ -99,7 +98,7 @@ const createBackboneSite = async function(req, res) { // const namesResult = await client.query("SELECT Name FROM InteriorSites WHERE Backbone = $1", [bid]); - let existingNames = []; + const existingNames = []; for (const row of namesResult.rows) { existingNames.push(row.name); } @@ -149,10 +148,10 @@ const updateBackboneSite = async function(req, res) { const form = new IncomingForm(); try { if (!IsValidUuid(sid)) { - throw(Error('Site-Id is not a valid uuid')); + throw new Error('Site-Id is not a valid uuid'); } - const [fields, files] = await form.parse(req); + const [fields] = await form.parse(req); const norm = ValidateAndNormalizeFields(fields, { 'name' : {type: 'string', optional: true, default: null}, 'metadata' : {type: 'string', optional: true, default: null}, @@ -161,14 +160,10 @@ const updateBackboneSite = async function(req, res) { const client = await ClientFromPool(); const notify = new NotifyTransaction(); try { - let nameChanged = false; - await queryWithContext(req, client, async (client) => { const siteResult = await client.query("SELECT * FROM InteriorSites WHERE Id = $1", [sid]); if (siteResult.rowCount == 1) { const site = siteResult.rows[0]; - let siteName = site.name; - // // If InteriorSite is CoLocated, no changes are allowed // @@ -180,9 +175,7 @@ const updateBackboneSite = async function(req, res) { // If the name has been changed, update the site record in the database // if (norm.name != null && norm.name != site.name) { - nameChanged = true; await client.query("UPDATE InteriorSites SET Name = $1 WHERE Id = $2", [norm.name, sid]); - siteName = norm.name; } // @@ -213,15 +206,15 @@ const updateBackboneSite = async function(req, res) { } const createAccessPoint = async function(req, res) { - var returnStatus; + let returnStatus; const sid = req.params.sid; const form = new IncomingForm(); try { if (!IsValidUuid(sid)) { - throw(Error('Site-Id is not a valid uuid')); + throw new Error('Site-Id is not a valid uuid'); } - const [fields, files] = await form.parse(req) + const [fields] = await form.parse(req) const norm = ValidateAndNormalizeFields(fields, { 'name' : {type: 'dnsname', optional: true, default: null}, 'kind' : {type: 'accesskind', optional: false}, @@ -301,7 +294,7 @@ const createAccessPoint = async function(req, res) { } const createBackboneLink = async function(req, res) { - var returnStatus; + let returnStatus; const apid = req.params.apid; const form = new IncomingForm(); try { @@ -309,7 +302,7 @@ const createBackboneLink = async function(req, res) { throw new Error('AccessPoint-Id is not a valid uuid'); } - const [fields, files] = await form.parse(req); + const [fields] = await form.parse(req); const norm = ValidateAndNormalizeFields(fields, { 'connectingsite' : {type: 'uuid', optional: false}, 'cost' : {type: 'number', optional: true, default: 1}, @@ -332,7 +325,7 @@ const createBackboneLink = async function(req, res) { // Validate that the referenced access point exists // if (accessResult.rowCount == 0) { - throw(Error(`Referenced access point not found: ${apid}`)); + throw new Error(`Referenced access point not found: ${apid}`); } const accessPoint = accessResult.rows[0]; @@ -340,7 +333,7 @@ const createBackboneLink = async function(req, res) { // Validate that the referenced access point is of kind 'peer' // if (accessPoint.kind != 'peer') { - throw(Error(`Referenced access point must be 'peer', found '${accessPoint.kind}'`)); + throw new Error(`Referenced access point must be 'peer', found '${accessPoint.kind}'`); } // @@ -348,11 +341,11 @@ const createBackboneLink = async function(req, res) { // const siteResult = await client.query("SELECT Backbone FROM InteriorSites WHERE Id = $1", [norm.connectingsite]); if (siteResult.rowCount == 0) { - throw(Error(`Referenced connecting site not found: ${norm.connectingsite}`)); + throw new Error(`Referenced connecting site not found: ${norm.connectingsite}`); } if (siteResult.rows[0].backbone != accessPoint.backbone) { - throw(Error(`Referenced connecting site is not in the same backbone network as the access-point`)); + throw new Error(`Referenced connecting site is not in the same backbone network as the access-point`); } // @@ -397,15 +390,15 @@ const createBackboneLink = async function(req, res) { } const updateBackboneLink = async function(req, res) { - var returnStatus = 204; + let returnStatus = 204; const lid = req.params.lid; const form = new IncomingForm(); try { if (!IsValidUuid(lid)) { - throw(Error('Link-Id is not a valid uuid')); + throw new Error('Link-Id is not a valid uuid'); } - const [fields, files] = await form.parse(req); + const [fields] = await form.parse(req); const norm = ValidateAndNormalizeFields(fields, { 'cost' : {type: 'number', optional: true, default: null}, }); @@ -479,7 +472,7 @@ const deleteBackbone = async function(req, res) { const colo = coloResult.rows[0]; notify.delete('InteriorSites', colo.id); } - const bbResult = await client.query("DELETE FROM Backbones WHERE Id = $1 RETURNING Certificate", [bid]); + await client.query("DELETE FROM Backbones WHERE Id = $1 RETURNING Certificate", [bid]); notify.delete('Backbones', bid); }); res.status(returnStatus).end(); @@ -565,10 +558,10 @@ const deleteBackboneSite = async function(req, res) { } const deleteAccessPoint = async function(req, res) { - var returnStatus = 204; + let returnStatus = 204; const apid = req.params.apid; - var siteId = undefined; - var wasManage = false; + let siteId; + let wasManage = false; const client = await ClientFromPool(); const notify = new NotifyTransaction(); try { @@ -922,7 +915,7 @@ const listSiteIngresses = async function(req, res) { } const listInvitations = async function(req, res) { - let returnStatus = 200; + const returnStatus = 200; const client = await ClientFromPool(); const result = await queryWithContext(req, client, async (client) => { diff --git a/components/management-controller/src/api-admin.test.js b/components/management-controller/src/api-admin.test.js index 6e38f971..d7cbf970 100644 --- a/components/management-controller/src/api-admin.test.js +++ b/components/management-controller/src/api-admin.test.js @@ -60,7 +60,7 @@ vi.mock('./db.js', async (importOriginal) => { describe('api-admin', () => { beforeEach(() => { vi.clearAllMocks(); - mockClient.query.mockImplementation(async (sql, params) => { + mockClient.query.mockImplementation(async (sql) => { if (sql === 'BEGIN' || sql === 'COMMIT' || sql === 'ROLLBACK') { return {}; } @@ -139,9 +139,10 @@ describe('api-admin', () => { it('GET /backbones returns 401 without authentication', async () => { const { app } = await buildApiApp({ includeUser: false }); - await request(app) - .get('/api/v1alpha1/backbones') - .expect(401); + const res = await request(app) + .get('/api/v1alpha1/backbones'); + + expect(res.status).toBe(401); }); it('GET /backbones returns 403 without list role', async () => { @@ -150,15 +151,16 @@ describe('api-admin', () => { roles: ['viewer'], }); - await request(app) + const res = await request(app) .get('/api/v1alpha1/backbones') - .set('x-test-auth', '1') - .expect(403); + .set('x-test-auth', '1'); + + expect(res.status).toBe(403); }); it('POST /backbones creates a backbone', async () => { mockFormFields = { name: 'new-backbone' }; - mockClient.query.mockImplementation(async (sql, params) => { + mockClient.query.mockImplementation(async (sql) => { if (sql === 'BEGIN' || sql === 'COMMIT' || sql === 'ROLLBACK') { return {}; } diff --git a/components/management-controller/src/api-user.js b/components/management-controller/src/api-user.js index 3f92eb74..5297b674 100644 --- a/components/management-controller/src/api-user.js +++ b/components/management-controller/src/api-user.js @@ -23,7 +23,6 @@ import { IncomingForm } from 'formidable'; import { ClientFromPool, queryWithContext } from './db.js'; import { Log } from '@skupperx/modules/log' import { IsValidUuid, ValidateAndNormalizeFields, UniquifyName } from '@skupperx/modules/util' -import { WatchNotify } from './watch-server.js'; import { NotifyTransaction } from './notify.js'; const API_PREFIX = '/api/v1alpha1/'; @@ -37,7 +36,7 @@ const createVan = async function(req, res) { throw new Error('Backbone-Id is not a valid uuid'); } - const [fields, files] = await form.parse(req); + const [fields] = await form.parse(req); const norm = ValidateAndNormalizeFields(fields, { 'name' : {type: 'dnsname', optional: false}, 'nettype' : {type: 'dnsname', optional: false}, @@ -57,7 +56,7 @@ const createVan = async function(req, res) { // If the name is not unique within the backbone, modify it to be unique. // const namesResult = await client.query("SELECT Name FROM ApplicationNetworks WHERE Backbone = $1", [bid]); - let existingNames = []; + const existingNames = []; for (const row of namesResult.rows) { existingNames.push(row.name); } @@ -134,7 +133,7 @@ const createInvitation = async function(req, res) { throw new Error('VAN-Id is not a valid uuid'); } - const [fields, files] = await form.parse(req) + const [fields] = await form.parse(req) const norm = ValidateAndNormalizeFields(fields, { 'name' : {type: 'dnsname', optional: false}, 'claimaccess' : {type: 'uuid', optional: false}, @@ -156,7 +155,7 @@ const createInvitation = async function(req, res) { // If the name is not unique within the backbone, modify it to be unique. // const namesResult = await client.query("SELECT Name FROM MemberInvitations WHERE MemberOf = $1", [vid]); - let existingNames = []; + const existingNames = []; for (const row of namesResult.rows) { existingNames.push(row.name); } @@ -229,7 +228,7 @@ const readVan = async function(req, res) { const vid = req.params.vid; const client = await ClientFromPool(); try { - const result = await queryWithContext(req, client, async (client, userInfo) => { + const result = await queryWithContext(req, client, async (client) => { return await client.query( "SELECT ApplicationNetworks.*, Backbones.Id as backboneid, Backbones.Name as backbonename " + "FROM ApplicationNetworks " + @@ -511,15 +510,15 @@ const readCertificate = async function(req, res) { } const evictMember = async function(req, res) { - const mid = req.params.mid; - let returnStatus = 501; + const _mid = req.params.mid; + const returnStatus = 501; res.status(returnStatus).send("Member eviction not implemented"); return returnStatus; } const evictVan = async function(req, res) { - const vid = req.params.vid; - let returnStatus = 501; + const _vid = req.params.vid; + const returnStatus = 501; res.status(returnStatus).send("Network eviction not implemented"); return returnStatus; } @@ -534,7 +533,7 @@ const listClaimAccessPoints = async function(req, res, ref) { `JOIN BackboneAccessPoints ON BackboneAccessPoints.Id = InteriorSites.${ref} ` + "WHERE InteriorSites.Backbone = $1", [bid]); }) - let data = []; + const data = []; for (const row of result.rows) { data.push({ id : row.accessid, @@ -656,4 +655,4 @@ export async function Initialize(api, auth) { api.get(API_PREFIX + 'backbones/:bid/access/member', auth.protect('realm:van-owner'), async (req, res) => { await listClaimAccessPoints(req, res, 'MemberAccess'); }); -} \ No newline at end of file +} diff --git a/components/management-controller/src/api-user.test.js b/components/management-controller/src/api-user.test.js index cdf7adaa..73482658 100644 --- a/components/management-controller/src/api-user.test.js +++ b/components/management-controller/src/api-user.test.js @@ -39,7 +39,7 @@ vi.mock('./db.js', async (importOriginal) => { describe('api-user', () => { beforeEach(() => { vi.clearAllMocks(); - mockClient.query.mockImplementation(async (sql, params) => { + mockClient.query.mockImplementation(async (sql) => { if (sql === 'BEGIN' || sql === 'COMMIT' || sql === 'ROLLBACK') { return {}; } @@ -146,18 +146,20 @@ describe('api-user', () => { const { app } = await buildApiApp({ includeAdmin: false }); - await request(app) + const res = await request(app) .get(`/api/v1alpha1/vans/${TEST_UUIDS.van}`) - .set('x-test-auth', '1') - .expect(400); + .set('x-test-auth', '1'); + + expect(res.status).toBe(400); }); it('GET /vans returns 401 without authentication', async () => { const { app } = await buildApiApp({ includeAdmin: false }); - await request(app) - .get('/api/v1alpha1/vans') - .expect(401); + const res = await request(app) + .get('/api/v1alpha1/vans'); + + expect(res.status).toBe(401); }); it('GET /vans returns 403 without can-list-vans role', async () => { @@ -166,9 +168,10 @@ describe('api-user', () => { roles: ['van-owner'], }); - await request(app) + const res = await request(app) .get('/api/v1alpha1/vans') - .set('x-test-auth', '1') - .expect(403); + .set('x-test-auth', '1'); + + expect(res.status).toBe(403); }); }); diff --git a/components/management-controller/src/backbone-links.js b/components/management-controller/src/backbone-links.js index ef9f783b..c0f931bb 100644 --- a/components/management-controller/src/backbone-links.js +++ b/components/management-controller/src/backbone-links.js @@ -33,8 +33,8 @@ let controller_name; let tls_ca; let tls_cert; let tls_key; -let manageConnections = {}; -let registrations = []; +const manageConnections = {}; +const registrations = []; async function createConnection(apid, row) { manageConnections[apid] = { @@ -74,7 +74,7 @@ async function periodicCheck() { const normal_period = 30000; const startup_period = 2000; await reconcileBackboneConnections(); - setTimeout(periodicCheck, !!tls_cert ? normal_period : startup_period); + setTimeout(periodicCheck, tls_cert ? normal_period : startup_period); } async function reconcileBackboneConnections() { diff --git a/components/management-controller/src/backbone-links.test.js b/components/management-controller/src/backbone-links.test.js index 60907783..937070a6 100644 --- a/components/management-controller/src/backbone-links.test.js +++ b/components/management-controller/src/backbone-links.test.js @@ -139,7 +139,7 @@ describe('resolveControllerRecord (via Start)', () => { }); it('inserts a management controller record when none exists', async () => { - mockClient.query.mockImplementation(async (sql, params) => { + mockClient.query.mockImplementation(async (sql) => { if (sql === 'BEGIN' || sql === 'COMMIT' || sql === 'ROLLBACK') { return {}; } @@ -147,7 +147,6 @@ describe('resolveControllerRecord (via Start)', () => { return { rowCount: 0, rows: [] }; } if (sql.includes('INSERT INTO ManagementControllers')) { - expect(params).toEqual(['test-controller']); return { rows: [{ id: 'mc-id-1' }] }; } return {}; diff --git a/components/management-controller/src/certs.js b/components/management-controller/src/certs.js index e1764fac..abe5f655 100644 --- a/components/management-controller/src/certs.js +++ b/components/management-controller/src/certs.js @@ -27,7 +27,6 @@ import { SiteCertificateChanged, AccessCertificateChanged } from './sync-managem import { CompleteMember } from './claim-server.js'; import { AccessPointCertReady, SiteLifecycleChanged_TX } from './site-deployment-state.js'; import { META_ANNOTATION_SKUPPERX_CONTROLLED } from '@skupperx/modules/common' -import { WatchNotify } from './watch-server.js'; import { NotifyTransaction, RegisterNotification } from './notify.js'; // @@ -43,8 +42,7 @@ async function onManagementControllersChange(action, id) { if (result.rowCount == 1) { const row = result.rows[0]; Log(`New Management Controller: ${row.name}`); - var duration_ms; - duration_ms = IntervalMilliseconds(BackboneExpiration()); + const duration_ms = IntervalMilliseconds(BackboneExpiration()); const cert = await client.query( "INSERT INTO CertificateRequests(Id, RequestType, CreatedTime, RequestTime, DurationHours, ManagementController) " + "VALUES(gen_random_uuid(), 'mgmtController', now(), now(), $1, $2) RETURNING Id", @@ -70,7 +68,7 @@ async function onManagementControllersChange(action, id) { // async function onBackbonesChange(action, id) { const client = await ClientFromPool('system'); - try { + try { await client.query('BEGIN'); const notify = new NotifyTransaction(); const result = await client.query("SELECT * FROM Backbones WHERE id = $1", [id]); @@ -79,8 +77,7 @@ async function onBackbonesChange(action, id) { if (backbone.lifecycle == 'new') { const row = result.rows[0]; Log(`New Backbone Network: ${row.name}`); - let duration_ms; - duration_ms = IntervalMilliseconds(BackboneExpiration()); + const duration_ms = IntervalMilliseconds(BackboneExpiration()); const cert = await client.query( "INSERT INTO CertificateRequests(Id, RequestType, CreatedTime, RequestTime, DurationHours, Backbone) " + "VALUES(gen_random_uuid(), 'backboneCA', now(), now(), $1, $2) RETURNING Id", @@ -255,7 +252,7 @@ async function onInteriorSitesChange(action, id) { if (result.rowCount == 1) { const row = result.rows[0]; Log(`New Interior Site: ${row.name}`); - let duration_ms = IntervalMilliseconds(DefaultCertExpiration()); + const duration_ms = IntervalMilliseconds(DefaultCertExpiration()); const cert = await client.query( "INSERT INTO CertificateRequests(Id, RequestType, CreatedTime, RequestTime, DurationHours, InteriorSite, Issuer) " + "VALUES(gen_random_uuid(), 'interiorRouter', now(), now(), $1, $2, $3) RETURNING Id", @@ -293,7 +290,7 @@ const onInvitationsChange = async function(action, id) { if (result.rowCount == 1) { const row = result.rows[0]; Log(`New Invitation: ${row.name}`); - let duration_ms = IntervalMilliseconds(DefaultCertExpiration()); + const duration_ms = IntervalMilliseconds(DefaultCertExpiration()); const cert = await client.query( "INSERT INTO CertificateRequests(Id, RequestType, CreatedTime, RequestTime, DurationHours, Invitation, Issuer) " + "VALUES(gen_random_uuid(), 'memberClaim', now(), now(), $1, $2, $3) RETURNING Id", @@ -331,7 +328,7 @@ async function onMemberSitesChange(action, id) { if (result.rowCount == 1) { const row = result.rows[0]; Log(`New Member Site: ${row.name}`); - let duration_ms = IntervalMilliseconds(DefaultCertExpiration()); + const duration_ms = IntervalMilliseconds(DefaultCertExpiration()); const cert = await client.query( "INSERT INTO CertificateRequests(Id, RequestType, CreatedTime, RequestTime, DurationHours, Site, Issuer) " + "VALUES(gen_random_uuid(), 'vanSite', now(), now(), $1, $2, $3) RETURNING Id", @@ -368,7 +365,7 @@ async function onNetworkCredentialsChange(action, id) { if (result.rowCount == 1) { const row = result.rows[0]; Log(`New Network Credential: ${row.name}`); - let duration_ms = IntervalMilliseconds(DefaultCertExpiration()); + const duration_ms = IntervalMilliseconds(DefaultCertExpiration()); const cert = await client.query( "INSERT INTO CertificateRequests(Id, RequestType, CreatedTime, RequestTime, DurationHours, NetworkCredential, Issuer) " + "VALUES(gen_random_uuid(), 'vanCredential', now(), now(), $1, $2, $3) RETURNING Id", @@ -388,7 +385,7 @@ async function onNetworkCredentialsChange(action, id) { } } -async function onCertificateRequestsChange(action, id) { +async function onCertificateRequestsChange(action, _id) { if (action === 'ADD') { await processCertificateRequests(true); } @@ -417,7 +414,7 @@ async function processCertificateRequests(nonrecurring) { let name; let is_ca; let issuer; - let extra_annotations = {}; + const extra_annotations = {}; let dns_name; let usage; switch (row.requesttype) { @@ -482,7 +479,7 @@ async function processCertificateRequests(nonrecurring) { } } - let cert_obj = certificateObject(name, row.durationhours, is_ca, issuer_name, row.id, row.issuer ? row.issuer : 'root', extra_annotations, name, dns_name, usage); + const cert_obj = certificateObject(name, row.durationhours, is_ca, issuer_name, row.id, row.issuer ? row.issuer : 'root', extra_annotations, name, dns_name, usage); await ApplyObject(cert_obj); await client.query("UPDATE CertificateRequests SET Lifecycle = 'cm_cert_created' WHERE Id = $1", [row.id]); notify.update('CertificateRequests', row.id); @@ -510,13 +507,13 @@ async function secretAdded(dblink, secret) { try { await client.query('BEGIN'); const result = await client.query("SELECT * FROM CertificateRequests WHERE Id = $1", [dblink]); - var ref_table; - var ref_id; - var ref_label; - var is_ca = false; - var alertSiteCertChanged = false; - var alertAccessCertChanged = false; - var alertMemberCompletion = false; + let ref_table; + let ref_id; + let ref_label; + let is_ca = false; + let alertSiteCertChanged = false; + let alertAccessCertChanged = false; + let alertMemberCompletion = false; if (result.rowCount == 1) { const cert_request = result.rows[0]; @@ -589,7 +586,7 @@ async function secretAdded(dblink, secret) { await client.query('DELETE FROM CertificateRequests WHERE Id = $1', [dblink]); notify.delete('CertificateRequests', dblink) if (is_ca) { - var issuer_obj = issuerObject(secret.metadata.name, secret.metadata.annotations['skupper.io/skx-dblink']); + const issuer_obj = issuerObject(secret.metadata.name, secret.metadata.annotations['skupper.io/skx-dblink']); await ApplyObject(issuer_obj); } Log(`Certificate${is_ca ? ' Authority' : ''} created: ${secret.metadata.name}`) @@ -641,13 +638,13 @@ async function secretAdded(dblink, secret) { const onSecretWatch = function(action, secret) { switch (action) { case 'ADDED': - const anno = secret.metadata.annotations; - if (anno && anno[META_ANNOTATION_SKUPPERX_CONTROLLED] == 'true') { - var dblink = anno['skupper.io/skx-dblink']; + { const anno = secret.metadata.annotations; + if (anno?.[META_ANNOTATION_SKUPPERX_CONTROLLED] == 'true') { + const dblink = anno['skupper.io/skx-dblink']; if (dblink) { secretAdded(dblink, secret); } - } + } } } } @@ -656,10 +653,8 @@ const onSecretWatch = function(action, secret) { // const onCertificateWatch = async function(action, cert) { if (action == 'MODIFIED' - && cert.metadata.annotations - && cert.metadata.annotations[META_ANNOTATION_SKUPPERX_CONTROLLED] == 'true' - && cert.status - && cert.status.notAfter + && cert.metadata.annotations?.[META_ANNOTATION_SKUPPERX_CONTROLLED] == 'true' + && cert.status?.notAfter && cert.status.renewalTime) { const notify = new NotifyTransaction(); const client = await ClientFromPool('system'); @@ -686,7 +681,7 @@ const onCertificateWatch = async function(action, cert) { // Generate a cert-manager Certificate object from a template. // const certificateObject = function(name, duration_hours, is_ca, issuer, db_link, issuer_link, extra_annotations, common_name, dns_name, usage) { - var cert = { + const cert = { apiVersion: 'cert-manager.io/v1', kind: 'Certificate', metadata: { @@ -765,28 +760,23 @@ const issuerObject = function(name, db_link) { async function ReconcileCertManager() { try { await GetIssuers(); - } catch (error) { + } catch { return false; } return true; } -const WatchCertManager = function() { - return new Promise(async (resolve) => { - const available = await ReconcileCertManager(); - if (available) { - resolve(); +const WatchCertManager = async function() { + if (await ReconcileCertManager()) { + return; + } + Log('WARNING: cert-manager is required but not found. The management controller needs cert-manager for TLS certificate management.'); + for (;;) { + await new Promise((resolve) => setTimeout(resolve, 10 * 1000)); + if (await ReconcileCertManager()) { return; } - Log('WARNING: cert-manager is required but not found. The management controller needs cert-manager for TLS certificate management.'); - const timer = setInterval(async () => { - const available = await ReconcileCertManager(); - if (available) { - clearInterval(timer); - resolve(); - } - }, 10 * 1000); - }); + } } @@ -807,4 +797,3 @@ export async function Start() { WatchSecrets(onSecretWatch); WatchCertificates(onCertificateWatch); } - diff --git a/components/management-controller/src/certs.test.js b/components/management-controller/src/certs.test.js index f47468d9..9fb77306 100644 --- a/components/management-controller/src/certs.test.js +++ b/components/management-controller/src/certs.test.js @@ -157,7 +157,7 @@ describe('onManagementControllersChange', () => { }); it('creates mgmtController certificate request for new controller rows', async () => { - mockClient.query.mockImplementation(async (sql, params) => { + mockClient.query.mockImplementation(async (sql) => { if (transactionSql(sql)) { return {}; } @@ -168,11 +168,9 @@ describe('onManagementControllersChange', () => { }; } if (sql.includes('INSERT INTO CertificateRequests')) { - expect(params[1]).toBe('mc-uuid-1'); return { rows: [{ id: 'cert-req-1' }] }; } if (sql.includes("UPDATE ManagementControllers SET Lifecycle = 'skx_cr_created'")) { - expect(params).toEqual(['mc-uuid-1']); return {}; } return {}; @@ -184,6 +182,10 @@ describe('onManagementControllersChange', () => { expect.stringContaining("'mgmtController'"), expect.arrayContaining(['mc-uuid-1']), ); + expect(mockClient.query).toHaveBeenCalledWith( + expect.stringContaining("UPDATE ManagementControllers SET Lifecycle = 'skx_cr_created'"), + ['mc-uuid-1'], + ); expect(notifyEvents).toContainEqual({ method: 'add', table: 'CertificateRequests', @@ -215,7 +217,7 @@ describe('onBackbonesChange', () => { }); it('creates backboneCA certificate request for new backbone rows', async () => { - mockClient.query.mockImplementation(async (sql, params) => { + mockClient.query.mockImplementation(async (sql) => { if (transactionSql(sql)) { return {}; } @@ -226,7 +228,6 @@ describe('onBackbonesChange', () => { }; } if (sql.includes('INSERT INTO CertificateRequests')) { - expect(params[1]).toBe('bb-uuid-1'); return { rows: [{ id: 'cert-req-2' }] }; } if (sql.includes("UPDATE Backbones SET Lifecycle = 'skx_cr_created'")) { @@ -362,7 +363,7 @@ describe('onBackboneAccessPointsChange', () => { }); it('creates accessPoint certificate request for new access points on ready backbones', async () => { - mockClient.query.mockImplementation(async (sql, params) => { + mockClient.query.mockImplementation(async (sql) => { if (transactionSql(sql)) { return {}; } @@ -380,7 +381,6 @@ describe('onBackboneAccessPointsChange', () => { }; } if (sql.includes('INSERT INTO CertificateRequests')) { - expect(params[1]).toBe('ap-uuid-1'); return { rows: [{ id: 'cert-req-ap-1' }] }; } if (sql.includes("UPDATE BackboneAccessPoints SET Lifecycle = 'skx_cr_created'")) { @@ -415,7 +415,7 @@ describe('onApplicationNetworksChange', () => { }); it('creates vanCA certificate request for new application networks', async () => { - mockClient.query.mockImplementation(async (sql, params) => { + mockClient.query.mockImplementation(async (sql) => { if (transactionSql(sql)) { return {}; } @@ -434,7 +434,6 @@ describe('onApplicationNetworksChange', () => { }; } if (sql.includes('INSERT INTO CertificateRequests')) { - expect(params[2]).toBe('van-uuid-1'); return { rows: [{ id: 'cert-req-van-1' }] }; } if (sql.includes("UPDATE ApplicationNetworks SET Lifecycle = 'skx_cr_created'")) { @@ -502,7 +501,7 @@ describe('onInteriorSitesChange', () => { }); it('creates interiorRouter certificate request for new interior sites', async () => { - mockClient.query.mockImplementation(async (sql, params) => { + mockClient.query.mockImplementation(async (sql) => { if (transactionSql(sql)) { return {}; } @@ -517,7 +516,6 @@ describe('onInteriorSitesChange', () => { }; } if (sql.includes('INSERT INTO CertificateRequests')) { - expect(params[1]).toBe('site-uuid-1'); return { rows: [{ id: 'cert-req-site-1' }] }; } if (sql.includes("UPDATE InteriorSites SET Lifecycle = 'skx_cr_created'")) { diff --git a/components/management-controller/src/claim-server.js b/components/management-controller/src/claim-server.js index a43435c3..c9d9a482 100644 --- a/components/management-controller/src/claim-server.js +++ b/components/management-controller/src/claim-server.js @@ -43,16 +43,16 @@ import { RegisterHandler } from './backbone-links.js'; import { HashOfData } from './resource-templates.js'; import { NotifyTransaction } from './notify.js'; -var backbones = {}; // backboneId => {conn: AMQP-Connection, sender: anon-sender, receiver: claim-receiver} -var memberCompletions = {}; // memberId => {handler: completion-function, result: undefined || {}, error: undefined || ERROR } +const backbones = {}; // backboneId => {conn: AMQP-Connection, sender: anon-sender, receiver: claim-receiver} +const memberCompletions = {}; // memberId => {handler: completion-function, result: undefined || {}, error: undefined || ERROR } // // This function completes the claim process after the member's certificate is created and ready. // Completion creates the claim-query response based on facts discovered in the database regarding the member site. // const memberCompletion = async function(memberId) { // => [outgoingLinks, siteClient] - var outgoingLinks; - var siteClient; + let outgoingLinks; + let siteClient; const client = await ClientFromPool('system'); try { await client.query("BEGIN"); @@ -63,7 +63,7 @@ const memberCompletion = async function(memberId) { // => [outgoingLinks, siteCl "JOIN TlsCertificates ON TlsCertificates.Id = Certificate " + "WHERE MemberSites.Id = $1", [memberId]); if (result.rowCount != 1) { - throw(Error(`Could not find MemberSite with Id ${memberId}`)); + throw new Error(`Could not find MemberSite with Id ${memberId}`); } const memberSite = result.rows[0]; @@ -89,12 +89,12 @@ const memberCompletion = async function(memberId) { // => [outgoingLinks, siteCl // // Gather the edge-link information for the outgoingLinks // - const linkResult = await client.query("SELECT EdgeLinks.*, BackboneAccessPoints.Id as bbid, BackboneAccessPoints.Hostname, BackboneAccessPoints.Port FROM EdgeLinks " + - "JOIN BackboneAccessPoints ON BackboneAccessPoints.Id = AccessPoint " + + const linkResult = await client.query("SELECT EdgeLinks.*, BackboneAccessPoints.Id as bbid, BackboneAccessPoints.Hostname, BackboneAccessPoints.Port FROM EdgeLinks " + + "JOIN BackboneAccessPoints ON BackboneAccessPoints.Id = AccessPoint " + "WHERE EdgeToken = $1", [memberSite.invitation]); outgoingLinks = []; for (const link of linkResult.rows) { - let linkObj = { + const linkObj = { apiVersion : 'v1', kind : 'ConfigMap', metadata : { @@ -152,11 +152,11 @@ const blockForCompletion = function(memberId) { const processClaim = async function(claimId, name) { - var statusCode = 200; - var statusDescription = 'OK'; - var outgoingLinks = null; - var siteClient = null; - var memberId; + let statusCode = 200; + let statusDescription = 'OK'; + let outgoingLinks = null; + let siteClient = null; + let memberId; const client = await ClientFromPool('system'); const notify = new NotifyTransaction(); @@ -164,7 +164,7 @@ const processClaim = async function(claimId, name) { await client.query("BEGIN"); const result = await client.query("SELECT * FROM MemberInvitations WHERE Id = $1 and (JoinDeadline IS NULL OR JoinDeadline > now())", [claimId]); if (result.rowCount != 1) { - throw(Error("No valid invitation exists for the claim")); + throw new Error("No valid invitation exists for the claim"); } // @@ -172,7 +172,7 @@ const processClaim = async function(claimId, name) { // const claim = result.rows[0]; if (claim.instancelimit && claim.instancecount == claim.instancelimit) { - throw(Error("Instance limit on this claim has been reached")); + throw new Error("Instance limit on this claim has been reached"); } // @@ -225,22 +225,22 @@ const processClaim = async function(claimId, name) { //========================================================================================================================= // Messaging Handlers //========================================================================================================================= -const onSendable = function(backboneId) { +const onSendable = function(_backboneId) { // // This function intentionally left blank // } -const onMessage = function(backboneId, application_properties, body, onReply) { +const onMessage = function(backboneId, _application_properties, body, onReply) { try { DispatchMessage(body, - async (site, hashset, address) => { // onHeartbeat + async (_site, _hashset, _address) => { // onHeartbeat }, - async (site, objectname) => { // onGet + async (_site, _objectname) => { // onGet }, async (claimId, name) => { // onClaim Log(`INFO:ClaimServer - Received claim for invitation ${claimId} via backbone ${backboneId}`); - let [statusCode, statusDescription, memberId, outgoingLinks, siteClient] = await processClaim(claimId, name); + const [statusCode, statusDescription, memberId, outgoingLinks, siteClient] = await processClaim(claimId, name); if (statusCode == 200) { onReply({}, AssertClaimResponseSuccess(memberId, outgoingLinks, siteClient)); } else { diff --git a/components/management-controller/src/colo-sync.js b/components/management-controller/src/colo-sync.js index 37322d71..f617b7a8 100644 --- a/components/management-controller/src/colo-sync.js +++ b/components/management-controller/src/colo-sync.js @@ -88,8 +88,6 @@ async function onSiteChange(action, sid) { coloNamespaces[ns].site = result.rows[0]; await visitNamespace(ns); } - } catch (error) { - throw error; } finally { client.release(); } @@ -112,8 +110,6 @@ async function onAccessPointChange(action, apid) { coloNamespaces[ns].accesspoint = result.rows[0]; await visitNamespace(ns); } - } catch (error) { - throw error; } finally { client.release(); } @@ -263,7 +259,7 @@ async function visitNamespace(ns) { async function runTheVisitQueue() { let ns = visitQueue.shift(); - while (!!ns) { + while (ns) { await doVisitNamespace(ns); ns = visitQueue.shift(); } @@ -367,7 +363,7 @@ async function doVisitNamespace(ns) { // const apName = 'vms-colo-manage'; const apSecretName = 'vms-colo-manage'; - let ap = await kube.LoadRouterAccess(apName, ns); + const ap = await kube.LoadRouterAccess(apName, ns); if (!ap) { const resource = resourceTemplates.RouterAccessColoManage(apName, apSecretName); await kube.ApplyObject(resource, ns); diff --git a/components/management-controller/src/config.js b/components/management-controller/src/config.js index ef93440a..c9d01ccf 100644 --- a/components/management-controller/src/config.js +++ b/components/management-controller/src/config.js @@ -22,8 +22,7 @@ import { QueryConfig } from './db.js'; import { Log } from '@skupperx/modules/log' -var config; -var changeListeners = []; +let config; export function RootIssuer() { return config.rootissuer; } export function DefaultCaExpiration() { return config.defaultcaexpiration; } @@ -32,23 +31,9 @@ export function CertOrganization() { return config.certorganization; } export function BackboneExpiration() { return config.backbonecaexpiration; } export function SiteControllerImage() { return config.sitecontrollerimage; } -const updateConfiguration = function() { - return QueryConfig() - .then(draft => config = draft) - .then(() => { - Log("Agent configuration:"); - Log(config); - changeListeners.forEach(onConfigChange => onConfigChange()); - }); -} - export function Start() { Log('[Config module starting]'); return QueryConfig() .then(result => config = result) .then(() => Log(config)); } - -export function Register(onConfigChange) { - changeListeners.push(onConfigChange); -} \ No newline at end of file diff --git a/components/management-controller/src/db.js b/components/management-controller/src/db.js index ed97468d..cde04777 100644 --- a/components/management-controller/src/db.js +++ b/components/management-controller/src/db.js @@ -52,7 +52,7 @@ export function QueryConfig () { export function IntervalMilliseconds (value) { try { - var result = 0; + let result = 0; for (const [unit, quantity] of Object.entries(value)) { if (unit == 'years' || unit == 'year') { result += quantity * (3600 * 24 * 365 * 1000); diff --git a/components/management-controller/src/external-vans.js b/components/management-controller/src/external-vans.js index b7afc4e6..56afc125 100644 --- a/components/management-controller/src/external-vans.js +++ b/components/management-controller/src/external-vans.js @@ -35,9 +35,9 @@ import { NotifyTransaction } from './notify.js'; const backbone_routers = {}; // backbone_id => RouterManagement async function getNetworkIds() { - let network_ids = []; + const network_ids = []; try { - for (const [bbid, router] of Object.entries(backbone_routers)) { + for (const [_bbid, router] of Object.entries(backbone_routers)) { const addresses = await router.listAddresses(['key']); for (const addr of addresses) { const kind = addr.key[0]; @@ -59,7 +59,7 @@ async function reconcileConnectedNetworks() { const notify = new NotifyTransaction(); try { await client.query("BEGIN"); - let pending_change = {}; + const pending_change = {}; const network_ids = await getNetworkIds(); const db_result = await client.query( "SELECT id, name, vanid, connected FROM ApplicationNetworks" @@ -87,7 +87,7 @@ async function reconcileConnectedNetworks() { await client.query("COMMIT"); await notify.commit(); - } catch (err) { + } catch { await client.query("ROLLBACK"); reschedule_delay = 10000; } finally { diff --git a/components/management-controller/src/external-vans.test.js b/components/management-controller/src/external-vans.test.js index b4e52cc8..dc16bbbe 100644 --- a/components/management-controller/src/external-vans.test.js +++ b/components/management-controller/src/external-vans.test.js @@ -29,6 +29,8 @@ const mockRouterStart = vi.fn(async () => {}); /** @type {Function | undefined} */ let capturedLinkAdded; +/** @type {Function | undefined} */ +let capturedLinkDeleted; vi.mock('@skupperx/modules/router', () => ({ RouterManagement: vi.fn().mockImplementation(function RouterManagement(conn) { @@ -41,7 +43,7 @@ vi.mock('@skupperx/modules/router', () => ({ vi.mock('./backbone-links.js', () => ({ RegisterHandler: vi.fn((onAdded, onDeleted) => { capturedLinkAdded = onAdded; - expect(onDeleted).toBeTypeOf('function'); + capturedLinkDeleted = onDeleted; }), })); @@ -61,7 +63,7 @@ import { RegisterHandler } from './backbone-links.js'; import { Start } from './external-vans.js'; function mockNetworkQueries() { - mockClient.query.mockImplementation(async (sql, params) => { + mockClient.query.mockImplementation(async (sql) => { if (sql === 'BEGIN' || sql === 'COMMIT' || sql === 'ROLLBACK') { return {}; } @@ -76,7 +78,6 @@ function mockNetworkQueries() { }; } if (sql.includes('UPDATE ApplicationNetworks SET Connected')) { - expect(params).toEqual(['net-uuid-1', true]); return {}; } return { rows: [] }; @@ -87,6 +88,7 @@ describe('external-vans Start', () => { beforeEach(() => { vi.clearAllMocks(); capturedLinkAdded = undefined; + capturedLinkDeleted = undefined; mockClient.query.mockReset(); mockListAddresses.mockResolvedValue([]); }); @@ -109,6 +111,7 @@ describe('external-vans Start', () => { expect.any(Function), ); expect(capturedLinkAdded).toBeTypeOf('function'); + expect(capturedLinkDeleted).toBeTypeOf('function'); }); }); @@ -118,6 +121,7 @@ describe('external VAN reconcile', () => { vi.clearAllMocks(); mockClient.query.mockReset(); capturedLinkAdded = undefined; + capturedLinkDeleted = undefined; mockListAddresses.mockResolvedValue([]); mockClient.query.mockImplementation(async (sql) => { @@ -161,7 +165,7 @@ describe('external VAN reconcile', () => { }); it('marks connected networks disconnected when router address disappears', async () => { - mockClient.query.mockImplementation(async (sql, params) => { + mockClient.query.mockImplementation(async (sql) => { if (sql === 'BEGIN' || sql === 'COMMIT' || sql === 'ROLLBACK') { return {}; } @@ -176,7 +180,6 @@ describe('external VAN reconcile', () => { }; } if (sql.includes('UPDATE ApplicationNetworks SET Connected')) { - expect(params).toEqual(['net-uuid-2', false]); return {}; } return { rows: [] }; diff --git a/components/management-controller/src/mc-apiserver.js b/components/management-controller/src/mc-apiserver.js index 6fac415b..5eeb5f91 100644 --- a/components/management-controller/src/mc-apiserver.js +++ b/components/management-controller/src/mc-apiserver.js @@ -72,7 +72,7 @@ const vanProxy = {}; // { Id: { vanId, backboneName } } app.use(sessionParser); const link_config_map_yaml = function(name, data) { - let configMap = { + const configMap = { apiVersion: 'v1', kind: 'ConfigMap', metadata: { @@ -86,31 +86,6 @@ const link_config_map_yaml = function(name, data) { return "---\n" + yaml.dump(configMap); } -const claim_config_map = function(claimId, hostname, port, interactive, namePrefix) { - let configMap = { - apiVersion : 'v1', - kind : 'ConfigMap', - metadata : { - name : 'skupperx-claim', - annotations : { - [common.META_ANNOTATION_SKUPPERX_CONTROLLED] : 'true', - }, - }, - data: { - claimId : claimId, - host : hostname, - port : port, - interactive : interactive ? 'true' : 'false', - } - }; - - if (namePrefix) { - configMap.data.namePrefix = namePrefix; - } - - return configMap; -} - const fetchInvitationKube = async function (req, res) { const iid = req.params.iid; let returnStatus = 200; @@ -164,7 +139,7 @@ const fetchBackboneSiteSkupper2 = async function (req, res) { throw new Error("Not permitted, site not ready for deployment"); } const secret = await LoadSecret(site.objectname); - let output = []; + const output = []; output.push(resourceTemplates.ServiceAccount()); output.push(resourceTemplates.BackboneRole()); output.push(resourceTemplates.RoleBinding()); @@ -213,13 +188,13 @@ const fetchBackboneAccessPointsKube = async function (req, res) { throw new Error('Site not found'); } - let site = result.rows[0]; + const site = result.rows[0]; if (site.deploymentstate != 'ready-bootfinish') { throw new Error('Not permitted, site not ready for bootstrap deployment'); } - let output = []; + const output = []; const ap_result = await client.query("SELECT TlsCertificates.ObjectName, BackboneAccessPoints.Id as apid, Lifecycle, Kind FROM BackboneAccessPoints " + "JOIN TlsCertificates ON TlsCertificates.Id = Certificate " + "WHERE BackboneAccessPoints.InteriorSite = $1", [bsid]); @@ -227,7 +202,7 @@ const fetchBackboneAccessPointsKube = async function (req, res) { if (ap.lifecycle != 'ready') { throw new Error(`Certificate for access point of kind ${ap.kind} is not yet ready`); } - let secret = await LoadSecret(ap.objectname); + const secret = await LoadSecret(ap.objectname); output.push(resourceTemplates.Secret(secret, `skx-access-${ap.apid}`, common.INJECT_TYPE_ACCESS_POINT, `tls-server-${ap.apid}`)); } @@ -266,7 +241,7 @@ const fetchBackboneLinksOutgoingKube = async function (req, res) { const getVanConfigConnecting = async function (req, res) { const vid = req.params.vid const apid = req.params.apid - let exposeNetworkObserverConsole = req.query['expose-console'] === 'true'; + const exposeNetworkObserverConsole = req.query['expose-console'] === 'true'; let returnStatus = 200; const client = await ClientFromPool(); try { @@ -319,7 +294,7 @@ const getVanConfigNonConnecting = async function(req, res) { let returnStatus = 200; const client = await ClientFromPool(); try { - const result = await queryWithContext(req, client, async (client, userInfo) => { + const result = await queryWithContext(req, client, async (client) => { const result = await client.query("SELECT VanId FROM ApplicationNetworks WHERE id = $1", [vid]); if (result.rowCount == 0) { return {status: 404, text: 'Network not found'}; @@ -419,7 +394,7 @@ export async function AddHostToAccessPoint(req, siteId, apid, hostname, port) { await queryWithContext(req, client, async (client) => { const result = await client.query(`SELECT Id, Lifecycle, Hostname, Port, Kind FROM BackboneAccessPoints WHERE Id = $1 AND InteriorSite = $2`, [apid, siteId]); if (result.rowCount == 1) { - let access = result.rows[0]; + const access = result.rows[0]; if (access.hostname != hostname || access.port != port) { if (access.hostname) { throw new Error(`Referenced access (${access.access_ref}) already has a hostname`); @@ -449,7 +424,7 @@ const postBackboneIngress = async function (bsid, req, res) { const form = formidable(); try { let count = 0; - const [fields, files] = await form.parse(req); + const [fields] = await form.parse(req); for (const [apid, apdata] of Object.entries(fields)) { if (!util.IsValidUuid(apid)) { throw new Error(`Invalid access-point identifier ${apid}`); @@ -585,7 +560,7 @@ export async function Initialize(router, auth) { }); } -export async function Start(is_standalone) { +export async function Start(_is_standalone) { Log('[API Server module started]'); /** * When NODE_ENV is set to "production", the static build files will be served (this can be done with a deployment or in standalone mode) @@ -612,12 +587,12 @@ export async function Start(is_standalone) { router.get('/', auth.protect()); - morgan.token('ts', (req, res) => { + morgan.token('ts', (_req, _res) => { return new Date().toISOString(); }); router.use(morgan(':ts :remote-addr :remote-user :method :url :status :res[content-length] :response-time ms', { - skip: function(req, res) { return !!req._skip_log; } + skip: function(req, _res) { return !!req._skip_log; } })); await Initialize(router, auth); @@ -636,12 +611,12 @@ export async function Start(is_standalone) { res.status(500).send(err.message); }); router.all('/console/:vid*/api/v2alpha1*', auth.protect(), (req, res) => { - let vid = req.params.vid; + const vid = req.params.vid; if (!vanProxy[vid]) { return res.status(404).send(`Van ${vid} not found`); } - let targetVan = vanProxy[vid]; - let targetUrl = `http://skupper-console-${targetVan.vanId}.colo-${targetVan.backboneName}:8080`; + const targetVan = vanProxy[vid]; + const targetUrl = `http://skupper-console-${targetVan.vanId}.colo-${targetVan.backboneName}:8080`; Log(`Proxying ${req.url} to ${targetUrl}`); req.url = req.url.slice(`/console/${vid}`.length); proxy.web(req, res, { @@ -652,7 +627,7 @@ export async function Start(is_standalone) { // Serve skupper-console static files under /console/:vanId router.use('/console/:vanId*', auth.protect(), (req, res, next) => { - let vid = req.params.vanId; + const vid = req.params.vanId; if (!vanProxy[vid]) { return res.status(404).send(`Van ${vid} not found`); } @@ -677,7 +652,7 @@ export async function Start(is_standalone) { const server = app.listen(API_PORT, () => { let host = server.address().address; - let port = server.address().port; + const port = server.address().port; if (host[0] == ':') { host = '[' + host + ']'; } diff --git a/components/management-controller/src/mc-apiserver.test.js b/components/management-controller/src/mc-apiserver.test.js index 3ba78716..388e1249 100644 --- a/components/management-controller/src/mc-apiserver.test.js +++ b/components/management-controller/src/mc-apiserver.test.js @@ -61,7 +61,7 @@ vi.mock('./db.js', async (importOriginal) => { describe('mc-apiserver routes', () => { beforeEach(() => { vi.clearAllMocks(); - mockClient.query.mockImplementation(async (sql, params) => { + mockClient.query.mockImplementation(async (sql) => { if (sql === 'BEGIN' || sql === 'COMMIT' || sql === 'ROLLBACK') { return {}; } diff --git a/components/management-controller/src/prune.js b/components/management-controller/src/prune.js index ebab57bc..77671b63 100644 --- a/components/management-controller/src/prune.js +++ b/components/management-controller/src/prune.js @@ -36,14 +36,14 @@ const reconcileCertificates = async function() { const client = await ClientFromPool('system'); try { const result = await client.query("SELECT ObjectName FROM TlsCertificates"); - var db_cert_names = []; + const db_cert_names = []; result.rows.forEach(row => { db_cert_names.push(row.objectname); }); const issuer_list = await GetIssuers(); issuer_list.forEach(issuer => { - if (!db_cert_names.includes(issuer.metadata.name) && (issuer.metadata.annotations && issuer.metadata.annotations[META_ANNOTATION_SKUPPERX_CONTROLLED] == 'true')) { + if (!db_cert_names.includes(issuer.metadata.name) && issuer.metadata.annotations?.[META_ANNOTATION_SKUPPERX_CONTROLLED] == 'true') { DeleteIssuer(issuer.metadata.name); Log(` Deleted issuer: ${issuer.metadata.name}`); } @@ -51,7 +51,7 @@ const reconcileCertificates = async function() { const cert_list = await GetCertificates(); cert_list.forEach(cert => { - if (!db_cert_names.includes(cert.metadata.name) && (cert.metadata.annotations && cert.metadata.annotations[META_ANNOTATION_SKUPPERX_CONTROLLED] == 'true')) { + if (!db_cert_names.includes(cert.metadata.name) && cert.metadata.annotations?.[META_ANNOTATION_SKUPPERX_CONTROLLED] == 'true') { DeleteCertificate(cert.metadata.name); Log(` Deleted certificate: ${cert.metadata.name}`); } @@ -59,7 +59,7 @@ const reconcileCertificates = async function() { const secret_list = await GetSecrets(); secret_list.forEach(secret => { - if (!db_cert_names.includes(secret.metadata.name) && (secret.metadata.annotations && secret.metadata.annotations[META_ANNOTATION_SKUPPERX_CONTROLLED] == 'true')) { + if (!db_cert_names.includes(secret.metadata.name) && secret.metadata.annotations?.[META_ANNOTATION_SKUPPERX_CONTROLLED] == 'true') { DeleteSecret(secret.metadata.name); Log(` Deleted secret: ${secret.metadata.name}`); } @@ -76,7 +76,7 @@ export async function DeleteOrphanCertificates() { const notify = new NotifyTransaction(); try { await client.query("BEGIN"); - let deleteMap = {}; + const deleteMap = {}; const tlsResult = await client.query("SELECT Id, SignedBy FROM TlsCertificates"); for (const tlsRow of tlsResult.rows) { if (tlsRow.signedby) { diff --git a/components/management-controller/src/resource-templates.js b/components/management-controller/src/resource-templates.js index 759cc12a..a3b35304 100644 --- a/components/management-controller/src/resource-templates.js +++ b/components/management-controller/src/resource-templates.js @@ -28,7 +28,6 @@ import { META_ANNOTATION_STATE_KEY, META_ANNOTATION_STATE_HASH, STATE_TYPE_LINK, - STATE_TYPE_ACCESS_POINT, } from '@skupperx/modules/common' import { createHash } from 'node:crypto'; import { SiteControllerImage } from './config.js'; @@ -45,7 +44,7 @@ const DEPLOYMENT_NAME = 'skupperx-site'; export function HashOfData(data) { let text = ''; - let keys = Object.keys(data); + const keys = Object.keys(data); keys.sort(); for (const key of keys) { text += key + data[key]; @@ -62,7 +61,7 @@ export function HashOfConfigMap(cm) { } export function HashOfObjectNoChildren(obj) { - let data = {}; + const data = {}; for (const [key, value] of Object.entries(obj)) { if (typeof value != 'object') { data[key] = value; @@ -76,7 +75,7 @@ export function HashOfSpec(obj) { return HashOfData(obj.spec); } -export function BackboneSite(name, siteId) { +export function BackboneSite(name, _siteId) { return { apiVersion : CRD_API_VERSION, kind : 'Site', @@ -118,7 +117,7 @@ export function NetworkLinkCR(host, port, secret) { } export function LinkCR(linkId, data, secret) { - let link = { + const link = { apiVersion : 'skupper.io/v2alpha1', kind : 'Link', metadata : { @@ -160,7 +159,7 @@ export function AccessPointCR(apId, data) { case 'member': return accessPointRouterAccess(apId, data); default: - throw new Error(`Unknown access kind: ${access.kind}`); + throw new Error(`Unknown access kind: ${data.kind}`); } } @@ -206,7 +205,7 @@ export function RouterAccessColoManage(name, secretName) { const accessPointRouterAccess = function(apId, data) { const name = short_access_name(`${data.kind}-${apId}`); - let routerAccess = { + const routerAccess = { apiVersion : 'skupper.io/v2alpha1', kind : 'RouterAccess', metadata : { @@ -233,7 +232,7 @@ const accessPointRouterAccess = function(apId, data) { const accessPointNetworkAccess = function(apId, data) { const name = short_access_name(`${data.kind}-${apId}`); - let networkAccess = { + const networkAccess = { apiVersion : 'skupper.io/v2alpha1', kind : 'NetworkAccess', metadata : { @@ -256,7 +255,7 @@ const accessPointNetworkAccess = function(apId, data) { } export function ConnectorCR(name, port, routingKey, selector, tlsCredentials) { - let connector = { + const connector = { apiVersion: "skupper.io/v2alpha1", kind: "Connector", metadata: { @@ -274,7 +273,7 @@ export function ConnectorCR(name, port, routingKey, selector, tlsCredentials) { } export function InterNetworkIngressCR(name, routingKey, networkLink='', networkAccess='') { - let ingress = { + const ingress = { apiVersion: "skupper.io/v2alpha1", kind: "InterNetworkIngress", metadata: { @@ -284,16 +283,16 @@ export function InterNetworkIngressCR(name, routingKey, networkLink='', networkA routingKey: routingKey, } }; - if (!!networkLink) { + if (networkLink) { ingress.spec.networkLink = networkLink; - } else if (!!networkAccess) { + } else if (networkAccess) { ingress.spec.networkAccess = networkAccess; } return ingress; } export function Secret(certificate, profile_name, inject, stateKey) { - let secret = { + const secret = { apiVersion: 'v1', kind: 'Secret', type: 'kubernetes.io/tls', diff --git a/components/management-controller/src/site-deployment-state.js b/components/management-controller/src/site-deployment-state.js index 023b618c..33ad72c1 100644 --- a/components/management-controller/src/site-deployment-state.js +++ b/components/management-controller/src/site-deployment-state.js @@ -25,7 +25,6 @@ import { Log } from '@skupperx/modules/log' import { ClientFromPool } from './db.js'; -import { WatchNotify } from './watch-server.js'; import { NotifyTransaction } from './notify.js'; const evaluateSingleSite_TX = async function (client, notify, site) { diff --git a/components/management-controller/src/sync-management.js b/components/management-controller/src/sync-management.js index 519a21c9..dc38eeff 100644 --- a/components/management-controller/src/sync-management.js +++ b/components/management-controller/src/sync-management.js @@ -36,14 +36,14 @@ import { HashOfSecret, HashOfData } from './resource-templates.js'; import { SiteLifecycleChanged_TX } from './site-deployment-state.js'; import { NotifyTransaction, RegisterNotification } from './notify.js'; -var peers = {}; // {peerId: {pClass: <>, stuff}} +const peers = {}; // {peerId: {pClass: <>, stuff}} export async function GetBackboneLinks_TX(client, siteId) { const result = await client.query( 'SELECT InterRouterLinks.Id, InterRouterLinks.Cost, BackboneAccessPoints.Hostname, BackboneAccessPoints.Port FROM InterRouterLinks ' + 'JOIN BackboneAccessPoints ON BackboneAccessPoints.Id = InterRouterLinks.AccessPoint ' + 'WHERE ConnectingInteriorSite = $1', [siteId]); - let links = {}; + const links = {}; for (const link of result.rows) { if (link.hostname) { links[link.id] = { @@ -57,7 +57,7 @@ export async function GetBackboneLinks_TX(client, siteId) { } export async function GetBackboneAccessPoints_TX(client, siteId, initialOnly = false) { - let data = {}; + const data = {}; const result = await client.query( 'SELECT ap.Id, ap.Kind, ap.BindHost, ap.AccessType, s.CoLocated AS colocated FROM BackboneAccessPoints ap ' + 'JOIN InteriorSites s ON s.Id = ap.InteriorSite WHERE ap.InteriorSite = $1', [siteId]); @@ -95,8 +95,8 @@ async function onNewBackboneSite(peerId) { // - accessstatus- - Host/Port for an access point {host: <>, port: <>} // Log(`Detected backbone site: ${peerId}`); - var localState = {}; - var remoteState = {}; + const localState = {}; + const remoteState = {}; const client = await ClientFromPool('system'); const notify = new NotifyTransaction(); try { @@ -140,7 +140,7 @@ async function onNewBackboneSite(peerId) { // Don't sync the manage access point to colocated sites. continue; } - let apData = { + const apData = { kind : accessPoint.kind, }; if (accessPoint.bindhost) { @@ -201,7 +201,7 @@ async function onNewBackboneSite(peerId) { return [localState, remoteState]; } -async function onLostBackbone(peerId) { +async function onLostBackbone(_peerId) { // Nothing to do here - Consider adding status to the schema to indicate a stale site } @@ -245,8 +245,8 @@ async function onStateChangeBackbone(peerId, stateKey, hash, data) { } async function getStateTlsBackboneSite(siteId) { - var hash = null; - var data = null; + let hash = null; + let data = null; const client = await ClientFromPool('system'); try { await client.query("BEGIN"); @@ -270,8 +270,8 @@ async function getStateTlsBackboneSite(siteId) { } async function getStateTlsMemberSite(siteId) { - var hash = null; - var data = null; + let hash = null; + let data = null; const client = await ClientFromPool('system'); try { await client.query("BEGIN"); @@ -295,8 +295,8 @@ async function getStateTlsMemberSite(siteId) { } async function getStateTlsServer(apid) { - var hash = null; - var data = null; + let hash = null; + let data = null; const client = await ClientFromPool('system'); try { await client.query("BEGIN"); @@ -320,8 +320,8 @@ async function getStateTlsServer(apid) { } async function getStateAccessPoint(apId) { - var hash = null; - var data = null; + let hash = null; + let data = null; const client = await ClientFromPool('system'); try { await client.query("BEGIN"); @@ -348,8 +348,8 @@ async function getStateAccessPoint(apId) { } async function getStateBackboneLink(linkId) { - var hash = null; - var data = null; + let hash = null; + let data = null; const client = await ClientFromPool('system'); try { await client.query("BEGIN"); @@ -377,8 +377,8 @@ async function getStateBackboneLink(linkId) { } async function getStateMemberLink(linkId) { - var hash = null; - var data = null; + let hash = null; + let data = null; const client = await ClientFromPool('system'); try { await client.query("BEGIN"); @@ -426,8 +426,8 @@ async function getStateVanIds(vid) { } async function onStateRequestBackbone(peerId, stateKey) { - var hash = null; - var data = null; + let hash = null; + let data = null; if (stateKey.substring(0, 9) == 'tls-site-') { [hash, data] = await getStateTlsBackboneSite(stateKey.substring(9)); @@ -460,8 +460,8 @@ async function onNewMember(peerId) { // Remote state: none // Log(`Detected member site: ${peerId}`); - var localState = {}; - var remoteState = {}; + const localState = {}; + const remoteState = {}; const client = await ClientFromPool('system'); const notify = new NotifyTransaction(); try { @@ -474,7 +474,7 @@ async function onNewMember(peerId) { "JOIN TlsCertificates ON TlsCertificates.Id = MemberSites.Certificate " + "WHERE MemberSites.Id = $1", [peerId]); if (siteResult.rowCount != 1) { - throw Error(`MemberSite not found using id ${peerId}`); + throw new Error(`MemberSite not found using id ${peerId}`); } const site = siteResult.rows[0]; const secret = await LoadSecret(site.objectname); @@ -518,17 +518,17 @@ async function onNewMember(peerId) { return [localState, remoteState]; } -async function onLostMember(peerId) { +async function onLostMember(_peerId) { // TODO } -async function onStateChangeMember(peerId, stateKey, hash, data) { +async function onStateChangeMember(_peerId, _stateKey, _hash, _data) { // There is no local state on a member site } async function onStateRequestMember(peerId, stateKey) { - var hash = null; - var data = null; + let hash = null; + let data = null; if (stateKey.substring(0, 9) == 'tls-site-') { [hash, data] = await getStateTlsMemberSite(stateKey.substring(9)); @@ -544,8 +544,8 @@ async function onStateRequestMember(peerId, stateKey) { // Sync Handlers //========================================================================================================================= async function onNewPeer(peerId, peerClass) { - var localState; - var remoteState; + let localState; + let remoteState; peers[peerId] = { pClass : peerClass, } @@ -561,7 +561,7 @@ async function onNewPeer(peerId, peerClass) { async function onPeerLost(peerId) { const peer = peers[peerId]; - if (!!peer) { + if (peer) { if (peer.pClass == CLASS_MEMBER) { await onLostMember(peerId); } else if (peer.pClass == CLASS_BACKBONE) { @@ -574,7 +574,7 @@ async function onPeerLost(peerId) { async function onStateChange(peerId, stateKey, hash, data) { const peer = peers[peerId]; - if (!!peer) { + if (peer) { if (peer.pClass == CLASS_MEMBER) { await onStateChangeMember(peerId, stateKey, hash, data); } else if (peer.pClass == CLASS_BACKBONE) { @@ -584,10 +584,10 @@ async function onStateChange(peerId, stateKey, hash, data) { } async function onStateRequest(peerId, stateKey) { - var hash = null; - var data = null; + let hash = null; + let data = null; const peer = peers[peerId]; - if (!!peer) { + if (peer) { if (peer.pClass == CLASS_MEMBER) { [hash, data] = await onStateRequestMember(peerId, stateKey); } else if (peer.pClass == CLASS_BACKBONE) { @@ -705,7 +705,7 @@ export async function SiteIngressChanged(siteId, accessPointId) { [accessPointId]); if (result.rowCount == 1) { const row = result.rows[0]; - let ap = {kind : row.kind}; + const ap = {kind : row.kind}; if (row.bindhost) { ap.bindhost = row.bindhost; } @@ -744,7 +744,7 @@ export async function LinkChanged(connectingSiteId, linkId) { [linkId]); if (result.rowCount == 1) { const row = result.rows[0]; - var link = { + const link = { host : row.hostname, port : row.port, cost : row.cost, diff --git a/components/management-controller/src/watch-server.js b/components/management-controller/src/watch-server.js index 2d6529c4..e52c9616 100644 --- a/components/management-controller/src/watch-server.js +++ b/components/management-controller/src/watch-server.js @@ -23,7 +23,6 @@ import { WebSocketServer } from 'ws'; import rhea from 'rhea'; import { Log } from '@skupperx/modules/log'; -let app; let router; let wss; let container; @@ -80,7 +79,7 @@ class RouterResponse { this.send(data); } - redirect(data) { + redirect(_data) { if (this.isInitial) { this.message.body.statusCode = 401; this.message.body.content = 'Would Redirect'; @@ -150,14 +149,13 @@ async function sendUpdate(watch, isInitial) { release(); } }); - } catch (error) { + } catch { release(); } } export async function StartWatchServer(server, sessionParser, _app, _router) { Log('[Watch Server Starting]'); - app = _app; router = _router; container = rhea.create_container({container_id:'WATCH_SERVER'}); @@ -220,7 +218,7 @@ export async function StartWatchServer(server, sessionParser, _app, _router) { }); } -export async function WatchNotify(tableName, id, holdoff) { +export async function WatchNotify(tableName, id, _holdoff) { const tableIndex = watchIndex[tableName]; let watches = []; if (tableIndex) { diff --git a/components/site-controller/src/api-member.js b/components/site-controller/src/api-member.js index f6d5bf27..3ee8a8a8 100644 --- a/components/site-controller/src/api-member.js +++ b/components/site-controller/src/api-member.js @@ -67,10 +67,10 @@ const connectorObject = function(name, routingKey, port, selector) { } const createListener = async function(req, res) { - var returnStatus = 201; + let returnStatus = 201; const form = new IncomingForm(); try { - const [fields, files] = await form.parse(req) + const [fields] = await form.parse(req) const norm = ValidateAndNormalizeFields(fields, { 'name' : {type: 'string', optional: false}, 'routingkey' : {type: 'string', optional: false}, @@ -89,10 +89,10 @@ const createListener = async function(req, res) { } const createConnector = async function(req, res) { - var returnStatus = 201; + let returnStatus = 201; const form = new IncomingForm(); try { - const [fields, files] = await form.parse(req) + const [fields] = await form.parse(req) const norm = ValidateAndNormalizeFields(fields, { 'name' : {type: 'string', optional: false}, 'routingkey' : {type: 'string', optional: false}, @@ -110,15 +110,15 @@ const createConnector = async function(req, res) { return returnStatus; } -const readListener = async function(res, lid) { +const readListener = async function(res, _lid) { res.status(400).send('Not Implemented'); } -const readConnector = async function(res, cid) { +const readConnector = async function(res, _cid) { res.status(400).send('Not Implemented'); } -const readRoutingKey = async function(res, rkid) { +const readRoutingKey = async function(res, _rkid) { res.status(400).send('Not Implemented'); } @@ -134,11 +134,11 @@ const listRoutingKeys = async function(res) { res.status(400).send('Not Implemented'); } -const deleteListener = async function(res, lid) { +const deleteListener = async function(res, _lid) { res.status(400).send('Not Implemented'); } -const deleteConnector = async function(res, cid) { +const deleteConnector = async function(res, _cid) { res.status(400).send('Not Implemented'); } @@ -217,4 +217,4 @@ export async function Initialize(api) { } export async function Start() { -} \ No newline at end of file +} diff --git a/components/site-controller/src/claim.js b/components/site-controller/src/claim.js index f1c74a80..def5fd89 100644 --- a/components/site-controller/src/claim.js +++ b/components/site-controller/src/claim.js @@ -42,7 +42,7 @@ const LINK_CONFIG_MAP_NAME = 'skupperx-links-outgoing'; const CLAIM_SECRET_NAME = 'skupperx-claim'; const CLAIM_REQUEST_TIMEOUT_SECONDS = 30; -var claimState = { +const claimState = { interactive : true, status : 'awaiting-name', // processing, joined, failed namePrefix : '', @@ -57,9 +57,9 @@ const startClaim = async function(configMap, secret) { // // Extract the needed certificates and keys from the secret // - var tls_ca; - var tls_cert; - var tls_key; + let tls_ca; + let tls_cert; + let tls_key; for (const [key, value] of Object.entries(secret.data)) { if (key == 'ca.crt') { tls_ca = Buffer.from(value, 'base64'); @@ -73,9 +73,9 @@ const startClaim = async function(configMap, secret) { // // Extract the connection host and port from the config-map // - var claimId = configMap.data.claimId; - var host = configMap.data.host; - var port = configMap.data.port; + const claimId = configMap.data.claimId; + const host = configMap.data.host; + const port = configMap.data.port; claimState.namePrefix = configMap.data.namePrefix ? configMap.data.namePrefix + '-' : ''; if (!claimState.siteName || claimState.siteName == '') { @@ -87,15 +87,15 @@ const startClaim = async function(configMap, secret) { // Open the AMQP connection and sender for claim-assertion // Log(`Asserting claim ${claimId} for site ${claimState.siteName} via amqps://${host}:${port}`); - let claimConnection = OpenConnection('Claim', host, port, 'tls', tls_ca, tls_cert, tls_key); - let claimSender = await OpenSender('Claim', claimConnection, CLAIM_ASSERT_ADDRESS); + const claimConnection = OpenConnection('Claim', host, port, 'tls', tls_ca, tls_cert, tls_key); + const claimSender = await OpenSender('Claim', claimConnection, CLAIM_ASSERT_ADDRESS); // // Send the claim-assert request to the management controller // - const [ap, response] = await Request(claimSender, AssertClaim(claimId, claimState.siteName), {}, null, CLAIM_REQUEST_TIMEOUT_SECONDS); + const [_ap, response] = await Request(claimSender, AssertClaim(claimId, claimState.siteName), {}, null, CLAIM_REQUEST_TIMEOUT_SECONDS); if (response.statusCode != 200) { - throw(Error(`Claim Rejected: ${response.statusCode} - ${response.statusDescription}`)); + throw new Error(`Claim Rejected: ${response.statusCode} - ${response.statusDescription}`); } Log('Claim accepted'); claimState.status = 'joined'; @@ -135,12 +135,11 @@ const startClaim = async function(configMap, secret) { } const checkClaimState = async function() { - var claimConfigMap; - var memberConfigMapPresent = false; - var claimSecret; - var siteId; + let memberConfigMapPresent = false; + let claimSecret; + let siteId; - claimConfigMap = await LoadConfigmap(CLAIM_CONFIG_MAP_NAME); + const claimConfigMap = await LoadConfigmap(CLAIM_CONFIG_MAP_NAME); if (claimConfigMap) { claimState.interactive = claimConfigMap.data.interactive == 'true'; } @@ -151,11 +150,11 @@ const checkClaimState = async function() { siteId = memberConfigMap.data.siteId; memberConfigMapPresent = true; } - } catch (error) {} + } catch { /* empty */ } try { claimSecret = await LoadSecret(CLAIM_SECRET_NAME); - } catch (error) {} + } catch { /* empty */ } try { if (memberConfigMapPresent) { @@ -186,7 +185,7 @@ const checkClaimState = async function() { // // If neither config-map is present, check again after a delay. // - throw(Error(`ERROR:Claim - Expect configMaps ${CLAIM_CONFIG_MAP_NAME} or a valid link configuration`)); + throw new Error(`ERROR:Claim - Expect configMaps ${CLAIM_CONFIG_MAP_NAME} or a valid link configuration`); } } catch (error) { Log(`Claim-state check failed: ${error.message}`); @@ -203,7 +202,7 @@ export function GetClaimState () { return claimState; } -var interactiveClaimComplete; +let interactiveClaimComplete; export async function SetInteractiveName (name) { if (claimState.status == 'awaiting-name') { diff --git a/components/site-controller/src/hash.js b/components/site-controller/src/hash.js index ad15e3f5..5e48bb43 100644 --- a/components/site-controller/src/hash.js +++ b/components/site-controller/src/hash.js @@ -23,7 +23,7 @@ import { createHash } from 'node:crypto'; export function HashOfData(data) { let text = ''; - let keys = Object.keys(data); + const keys = Object.keys(data); keys.sort(); for (const key of keys) { text += key + data[key]; diff --git a/components/site-controller/src/ingress-v2.js b/components/site-controller/src/ingress-v2.js index 3b2a0c3a..48025863 100644 --- a/components/site-controller/src/ingress-v2.js +++ b/components/site-controller/src/ingress-v2.js @@ -44,7 +44,7 @@ import { createHash } from 'node:crypto'; const accessPoints = {}; // APID => {kind, name, syncHash, syncData} const newAccessPoint = function(apId, kind, name, syncData) { - let value = { + const value = { kind : kind, name : name, apId : apId, @@ -71,7 +71,7 @@ export function GetAccessPointKind(stateId) { function getAccessPointKindFromAccess(access) { if (Controlled(access)) { - let kind = access.metadata.name.split('-')[0]; + const kind = access.metadata.name.split('-')[0]; return kind; } throw new Error(`${access.kind} is not controlled: ${access.metadata.name}`); @@ -120,7 +120,7 @@ const handleAccessResource = async function(oper, access) { return; } const syncData = await getAccessEndpoint(access); - let ap = newAccessPoint(apId, apKind, name, syncData); + const ap = newAccessPoint(apId, apKind, name, syncData); const existing = accessPoints[apId]; if (existing && existing.syncHash == ap.syncHash) { return; @@ -150,12 +150,12 @@ const ingressHash = function(data) { return null; } - let text = 'host' + data.host + 'port' + data.port; + const text = 'host' + data.host + 'port' + data.port; return createHash('sha1').update(text).digest('hex'); } export function GetIngressBundle() { - let bundle = {}; + const bundle = {}; for (const [apid, ap] of Object.entries(accessPoints)) { if (ap.syncHash) { @@ -174,7 +174,7 @@ export async function GetInitialState() { } export function GetIngressBundleV2() { - let bundle = {}; + const bundle = {}; for (const [apid, ap] of Object.entries(accessPoints)) { if (ap.syncHash) { bundle[apid] = { diff --git a/components/site-controller/src/router-port.js b/components/site-controller/src/router-port.js index 6e729929..9e483a13 100644 --- a/components/site-controller/src/router-port.js +++ b/components/site-controller/src/router-port.js @@ -27,9 +27,9 @@ const FIRST_EPHEMERAL_PORT = 1050; const API_PORT = 1040; // The port for the site-controller API const reserved_ports = [5672, 9090]; // Ports that must never be allocated -var next_port = FIRST_EPHEMERAL_PORT; -var free_list = []; // Ports that were freed and may be re-allocated -var pre_taken_list = []; // Ports that were pre-allocated and must not be allocated (ports greater than next_port) +let next_port = FIRST_EPHEMERAL_PORT; +const free_list = []; // Ports that were freed and may be re-allocated +const pre_taken_list = []; // Ports that were pre-allocated and must not be allocated (ports greater than next_port) export function GetApiPort() { return API_PORT; @@ -42,7 +42,7 @@ export function TakePort(port) { } export function AllocatePort() { - var new_port; + let new_port; if (free_list.length > 0) { new_port = free_list.shift(); } else { diff --git a/components/site-controller/src/sc-apiserver.js b/components/site-controller/src/sc-apiserver.js index 1a416b4d..6c2770d2 100644 --- a/components/site-controller/src/sc-apiserver.js +++ b/components/site-controller/src/sc-apiserver.js @@ -30,10 +30,10 @@ import { Initialize as initializeMemberApi } from './api-member.js'; import { GetApiPort } from './router-port.js'; const API_PREFIX = '/api/v1alpha1/'; -var api; +let api; const getHostnames = function(res) { - let ingress_bundle = GetIngressBundleV2(); + const ingress_bundle = GetIngressBundleV2(); res.status(200).json(ingress_bundle); return 200; } @@ -45,10 +45,10 @@ const getSiteStatus = function(res) { } const startClaim = async function(req, res) { - var returnStatus; + let returnStatus; const form = new IncomingForm(); try { - const [fields, files] = await form.parse(req); + const [fields] = await form.parse(req); const norm = ValidateAndNormalizeFields(fields, { 'name' : {type: 'dnsname', optional: false}, }); @@ -104,14 +104,14 @@ export async function Initialize(app, { backboneMode = false, includeMemberApi = } } -export async function Start(backboneMode, platform) { +export async function Start(backboneMode, _platform) { Log('[API Server module started]'); api = createApiApp(); await Initialize(api, { backboneMode, includeMemberApi: true }); - let server = api.listen(GetApiPort(), () => { + const server = api.listen(GetApiPort(), () => { let host = server.address().address; - let port = server.address().port; + const port = server.address().port; if (host[0] == ':') { host = '[' + host + ']'; } diff --git a/components/site-controller/src/sc-main.js b/components/site-controller/src/sc-main.js index 50ce2cc5..90b25af3 100644 --- a/components/site-controller/src/sc-main.js +++ b/components/site-controller/src/sc-main.js @@ -36,7 +36,7 @@ const VERSION = '0.2.0'; const STANDALONE_NAMESPACE = process.env.SKX_STANDALONE_NAMESPACE; const BACKBONE_MODE = (process.env.SKX_BACKBONE || 'NO') == 'YES'; const PLATFORM = process.env.SKX_PLATFORM || 'unknown'; -var site_id = process.env.SKUPPERX_SITE_ID || 'unknown'; +let site_id = process.env.SKUPPERX_SITE_ID || 'unknown'; Log(`Skupper-X Site controller version ${VERSION}`); Log(`Backbone : ${BACKBONE_MODE}`); @@ -72,14 +72,13 @@ export async function Main() { if (BACKBONE_MODE) { await ingress_v2.Start(site_id); } - let conn; Log('Waiting for skupper-router pod to be Running...'); if (!kube.waitPodsRunning(kube.Namespace(), 'application=skupper-router')) { Log('Skupper-router is not running, exiting'); process.exit(1); } - let certs = await GetLocalRouterCerts(); - conn = amqp.OpenConnection('LocalRouter', 'skupper-router-local', '5671', 'tls', certs.ca, certs.cert, certs.key); + const certs = await GetLocalRouterCerts(); + const conn = amqp.OpenConnection('LocalRouter', 'skupper-router-local', '5671', 'tls', certs.ca, certs.cert, certs.key); await syncKube.Start(site_id, conn, BACKBONE_MODE, PLATFORM); Log("[Site controller initialization completed successfully]"); } catch (error) { diff --git a/components/site-controller/src/sync-site-kube.js b/components/site-controller/src/sync-site-kube.js index 22aa2837..2db1e38f 100644 --- a/components/site-controller/src/sync-site-kube.js +++ b/components/site-controller/src/sync-site-kube.js @@ -85,26 +85,25 @@ import { import { GetInitialState, GetRouterAccessRole, GetAccessPointKind } from './ingress-v2.js'; import { HashOfData } from './hash.js'; -var backbone_mode; -var backboneClientSecret; -var platform; -var connectedToPeer = false; -var peerId; -var localState = {}; // state-key: {hash, data} +let backbone_mode; +let backboneClientSecret; +let connectedToPeer = false; +let peerId; +const localState = {}; // state-key: {hash, data} const kubeObjectForState = function(stateKey, data=null) { const elements = stateKey.split('-'); - var objName = 'skx-' + stateKey; - var objDir = 'remote'; - var apiVersion = 'v1'; - var objKind; - var objType; - var stateType; - var stateId; - var inject; + let objName = 'skx-' + stateKey; + let objDir = 'remote'; + let apiVersion = 'v1'; + let objKind; + let objType; + let stateType; + let stateId; + let inject; if (elements.length < 2) { - throw(Error(`Malformed stateKey: ${stateKey}`)); + throw new Error(`Malformed stateKey: ${stateKey}`); } switch (elements[0]) { @@ -120,11 +119,11 @@ const kubeObjectForState = function(stateKey, data=null) { objName = `skx-access-${stateId}`; inject = INJECT_TYPE_ACCESS_POINT; } else { - throw(Error(`Invalid stateKey prefix ${elements[0]}-${elements[1]}`)); + throw new Error(`Invalid stateKey prefix ${elements[0]}-${elements[1]}`); } break; case 'access': - stateType = STATE_TYPE_ACCESS_POINT; + { stateType = STATE_TYPE_ACCESS_POINT; stateId = stateKey.substring(7); // text following 'access-' apiVersion = 'skupper.io/v2alpha1'; objKind = 'RouterAccess'; @@ -136,7 +135,7 @@ const kubeObjectForState = function(stateKey, data=null) { objKind = 'NetworkAccess'; } objName = apKind + '-' + stateId.split('-')[0]; - break; + break; } case 'link': apiVersion = 'skupper.io/v2alpha1'; objKind = 'Link'; @@ -154,7 +153,7 @@ const kubeObjectForState = function(stateKey, data=null) { stateId = stateKey.substring(4); // text following 'van-' break; default: - throw(Error(`Invalid stateKey prefix: ${elements[0]}`)) + throw new Error(`Invalid stateKey prefix: ${elements[0]}`) } return [objName, apiVersion, objKind, objType, objDir, stateType, stateId, inject]; @@ -185,8 +184,8 @@ const stateInMemory = function(local) { } const getInitialHashState = async function() { - var local = {}; - var remote = {}; + let local = {}; + let remote = {}; const secrets = await GetSecrets(); const configmaps = await GetConfigmaps(); const deployments = await GetDeployments(); @@ -229,13 +228,13 @@ const doStateChangeSpec = async function(obj, data) { } } -const onNewPeer = async function(_peerId, peerClass) { +const onNewPeer = async function(_peerId, _peerClass) { connectedToPeer = true; peerId = _peerId; return await getInitialHashState(); } -const onPeerLost = async function(peerId) { +const onPeerLost = async function(_peerId) { connectedToPeer = false; peerId = undefined; } @@ -264,9 +263,9 @@ const retrieveLatest = async function(apiVersion, objKind, objName) { } const updateObject = async function(obj) { - let apiVersion = obj.apiVersion; - let objKind = obj.kind; - let objName = obj.metadata.name; + const apiVersion = obj.apiVersion; + const objKind = obj.kind; + const objName = obj.metadata.name; Log(`Updating object - kind: ${apiVersion}.${objKind}, name: ${objName}`) if (apiVersion == "skupper.io/v2alpha1") { switch (objKind) { @@ -336,10 +335,10 @@ async function syncListenerSpec(obj, data) { } async function getBackboneClientSecret() { - if (!!backboneClientSecret) { + if (backboneClientSecret) { return backboneClientSecret; } - for (let secret of await GetSecrets()) { + for (const secret of await GetSecrets()) { if (!Controlled(secret) || Annotation(secret, META_ANNOTATION_TLS_INJECT) != INJECT_TYPE_SITE) { continue; } @@ -354,14 +353,14 @@ async function getBackboneClientSecret() { const onStateChange = async function(peerId, stateKey, hash, data) { const [objName, apiVersion, objKind, objType, objDir, stateType, stateId, inject] = kubeObjectForState(stateKey, data); if (objDir == 'local') { - throw(Error(`Protocol error: Received update for local state ${stateKey}`)); + throw new Error(`Protocol error: Received update for local state ${stateKey}`); } if (objName == 'spec') { await doStateChangeSpec(hash, data); } else { - if (!!hash) { - let isSkupperResource = apiVersion == 'skupper.io/v2alpha1'; + if (hash) { + const isSkupperResource = apiVersion == 'skupper.io/v2alpha1'; let obj = await retrieveLatest(apiVersion, objKind, objName); let create = true; if (!obj) { @@ -378,7 +377,7 @@ const onStateChange = async function(peerId, stateKey, hash, data) { }, }; } else { - let existing_hash = Annotation(obj, META_ANNOTATION_STATE_HASH); + const existing_hash = Annotation(obj, META_ANNOTATION_STATE_HASH); if (existing_hash == hash) { Log(`Ignoring state change for kind: ${apiVersion}/${objKind}, name: ${objName} as hash is unchanged: ${hash}`); return; @@ -436,13 +435,13 @@ const onStateChange = async function(peerId, stateKey, hash, data) { } const onStateRequest = async function(peerId, stateKey) { - const [objName, apiVersion, objKind, objType, objDir] = kubeObjectForState(stateKey); + const [objName, _apiVersion, objKind, _objType, objDir] = kubeObjectForState(stateKey); if (objDir == 'remote') { - throw(Error(`Protocol error: Received request for remote state ${stateKey}`)); + throw new Error(`Protocol error: Received request for remote state ${stateKey}`); } - var obj; - var hash; + let obj; + let hash; try { if (objKind == 'Secret') { // No local secrets currently @@ -455,17 +454,17 @@ const onStateRequest = async function(peerId, stateKey) { obj = { data : localState[stateKey].data }; hash = localState[stateKey].hash; } - } catch (error) { + } catch { hash = null; } - if (!!hash) { + if (hash) { return [hash, obj.data]; } return [null, null]; } -const onPing = async function(siteId) { +const onPing = async function(_siteId) { // This function intentionally left blank } @@ -486,7 +485,6 @@ export async function UpdateLocalState(stateKey, stateHash, stateData) { export async function Start(siteId, conn, _backbone_mode, _platform) { backbone_mode = _backbone_mode; - platform = _platform; Log(`[Sync-Site-Kube module started]`); await StateSyncStart(backbone_mode ? CLASS_BACKBONE : CLASS_MEMBER, siteId, undefined, onNewPeer, onPeerLost, onStateChange, onStateRequest, onPing); await AddTarget(API_CONTROLLER_ADDRESS); diff --git a/modules/src/amqp.js b/modules/src/amqp.js index 9dc83f06..74f7980a 100644 --- a/modules/src/amqp.js +++ b/modules/src/amqp.js @@ -19,10 +19,10 @@ import { Log } from "./log.js" -var container -var nextCid = 1 -var nextMessageId = 1 -var inFlight = {} // { cid : handler } +let container +let nextCid = 1 +let nextMessageId = 1 +const inFlight = {} // { cid : handler } const DEFAULT_TIMEOUT_SECONDS = 5 @@ -35,7 +35,7 @@ const rhea_handlers = function () { }) container.on("receiver_open", function (context) { - let conn = context.connection.skxConn + const conn = context.connection.skxConn if (context.receiver == conn.replyReceiver) { const firstTime = conn.replyTo == undefined conn.replyTo = context.receiver.source.address @@ -52,15 +52,15 @@ const rhea_handlers = function () { }) } } else { - let rx = context.receiver.skxReceiver - if (rx && rx.onAddress) { + const rx = context.receiver.skxReceiver + if (rx?.onAddress) { rx.onAddress(rx.context, context.receiver.source.address) } } }) container.on("sendable", function (context) { - let conn = context.connection.skxConn + const conn = context.connection.skxConn conn.senders.forEach((sender) => { if (sender.amqpSender == context.sender) { if (!sender.notified) { @@ -76,10 +76,10 @@ const rhea_handlers = function () { }) container.on("message", function (context) { - let conn = context.connection.skxConn - let message = context.message - let cid = message.correlation_id - var handler + const conn = context.connection.skxConn + const message = context.message + const cid = message.correlation_id + let handler if (context.receiver == conn.replyReceiver) { if (cid) { handler = inFlight[cid] @@ -120,7 +120,7 @@ export function OpenConnection( cert = undefined, key = undefined, ) { - let conn = { + const conn = { amqpConnection: container.connect({ host: host, hostname: host, @@ -160,7 +160,7 @@ export function OpenSender( // // This is the synchronous version of the function // - let sender = { + const sender = { conn: conn, amqpSender: conn.amqpConnection.open_sender(address), onSendable: onSendable, @@ -178,8 +178,8 @@ export function OpenSender( // // This is the asynchronous version of the function which does not resolve until the sender is sendable // - return new Promise((resolve, reject) => { - let sender = { + return new Promise((resolve) => { + const sender = { conn: conn, amqpSender: null, onSendable: null, @@ -189,7 +189,7 @@ export function OpenSender( notified: false, } - sender.onSendable = (unusedContext) => { + sender.onSendable = (_unusedContext) => { resolve(sender) } @@ -201,7 +201,7 @@ export function OpenSender( } export function OpenReceiver(conn, address, onMessage, context = undefined) { - let receiver = { + const receiver = { amqpReceiver: conn.amqpConnection.open_receiver(address), onMessage: onMessage, onAddress: null, @@ -220,7 +220,7 @@ export function OpenDynamicReceiver( onAddress, context = undefined, ) { - let receiver = { + const receiver = { amqpReceiver: conn.amqpConnection.open_receiver({ source: { dynamic: true }, }), @@ -238,7 +238,7 @@ export function OpenDynamicReceiver( export function SendMessage(sender, messageBody, ap = {}, destination = null) { const messageId = nextMessageId nextMessageId++ - let message = { + const message = { message_id: messageId, reply_to: sender.conn.replyTo, body: messageBody, @@ -260,9 +260,9 @@ export function Request( return new Promise((resolve, reject) => { const cid = nextCid const msgId = nextMessageId - let timer = setTimeout(() => { + const timer = setTimeout(() => { delete inFlight[cid] - reject(Error("AMQP request/response timeout")) + reject(new Error("AMQP request/response timeout")) }, timeoutSeconds * 1000) nextMessageId++ nextCid++ @@ -270,7 +270,7 @@ export function Request( clearTimeout(timer) resolve([response.application_properties, response.body]) } - let message = { + const message = { message_id: msgId, reply_to: sender.conn.replyTo, correlation_id: cid, diff --git a/modules/src/kube.js b/modules/src/kube.js index e6a72305..1137ac39 100644 --- a/modules/src/kube.js +++ b/modules/src/kube.js @@ -22,28 +22,28 @@ import * as common from "./common.js" const WATCH_ERROR_THRESHOLD = 10 // Log if threshold is exceeded in a minute's time. -var fs -var YAML -var k8s -var kc -var client -var v1Api -var v1AppApi -var customApi -var secretWatch -var certificateWatch -var configMapWatch -var routeWatch -var serviceWatch -var podWatch -var routerAccessWatch -var networkAccessWatch -var watchErrorCount = 0 -var lastWatchError -var namespace = "default" +let fs +let YAML +let k8s +let kc +let client +let v1Api +let v1AppApi +let customApi +let secretWatch +let certificateWatch +let configMapWatch +let routeWatch +let serviceWatch +let podWatch +let routerAccessWatch +let networkAccessWatch +let watchErrorCount = 0 +let lastWatchError +let namespace = "default" export function Annotation(obj, key) { - if (obj && obj.metadata && obj.metadata.annotations) { + if (obj?.metadata?.annotations) { return obj.metadata.annotations[key] } @@ -94,13 +94,13 @@ export async function Start(k8s_mod, fs_mod, yaml_mod, standalone_namespace) { ) } Log(`Running in namespace: ${namespace}`) - } catch (err) { + } catch { Log(`Unable to determine namespace, assuming ${namespace}`) } } export async function GetIssuers() { - let list = await customApi.listNamespacedCustomObject({ + const list = await customApi.listNamespacedCustomObject({ group: "cert-manager.io", version: "v1", namespace: namespace, @@ -130,7 +130,7 @@ export async function DeleteIssuer(name) { } export async function GetCertificates() { - let list = await customApi.listNamespacedCustomObject({ + const list = await customApi.listNamespacedCustomObject({ group: "cert-manager.io", version: "v1", namespace: namespace, @@ -160,7 +160,7 @@ export async function DeleteCertificate(name) { } export async function GetSecrets() { - let list = await v1Api.listNamespacedSecret({ namespace: namespace }) + const list = await v1Api.listNamespacedSecret({ namespace: namespace }) return list.items } @@ -170,8 +170,9 @@ export async function LoadSecret(name, ns) { name: name, namespace: ns || namespace, }) - } catch (e) {} - return undefined + } catch { + return undefined + } } export async function ReplaceSecret(name, obj) { @@ -188,7 +189,7 @@ export async function DeleteSecret(name) { } export async function GetConfigmaps() { - let list = await v1Api.listNamespacedConfigMap({ namespace: namespace }) + const list = await v1Api.listNamespacedConfigMap({ namespace: namespace }) return list.items } @@ -198,8 +199,9 @@ export async function LoadConfigmap(name) { name: name, namespace: namespace, }) - } catch (e) {} - return undefined + } catch { + return undefined + } } export async function ReplaceConfigmap(name, obj) { @@ -248,7 +250,7 @@ export async function deleteNamespace(name) { } export async function GetPods() { - let list = await v1Api.listNamespacedPod({ namespace: namespace }) + const list = await v1Api.listNamespacedPod({ namespace: namespace }) return list.items } @@ -259,7 +261,7 @@ export async function getPodsByLabel(ns, labelSelector) { labelSelector: labelSelector }); return response.items; - } catch (err) { + } catch { return [] } } @@ -268,11 +270,11 @@ export async function waitPodsRunning(ns, label, interval=1000, attempts=30) { for (let i=0; i { + (type, apiObj, _watchObj) => { for (const callback of secretWatches) { callback(type, apiObj) } @@ -549,13 +554,13 @@ export function WatchSecrets(callback) { } } -var configMapWatches = [] +const configMapWatches = [] const startWatchConfigMaps = function () { configMapWatch.watch( `/api/v1/namespaces/${namespace}/configmaps`, {}, - (type, apiObj, watchObj) => { + (type, apiObj, _watchObj) => { for (const callback of configMapWatches) { callback(type, apiObj) } @@ -577,13 +582,13 @@ export function WatchConfigMaps(callback) { } } -var certificateWatches = [] +const certificateWatches = [] const startWatchCertificates = function () { certificateWatch.watch( `/apis/cert-manager.io/v1/namespaces/${namespace}/certificates`, {}, - (type, apiObj, watchObj) => { + (type, apiObj, _watchObj) => { for (const callback of certificateWatches) { callback(type, apiObj) } @@ -605,13 +610,13 @@ export function WatchCertificates(callback) { } } -var routeWatches = [] +const routeWatches = [] const startWatchRoutes = function () { routeWatch.watch( `/apis/route.openshift.io/v1/namespaces/${namespace}/routes`, {}, - (type, apiObj, watchObj) => { + (type, apiObj, _watchObj) => { for (const callback of routeWatches) { callback(type, apiObj) } @@ -633,13 +638,13 @@ export function WatchRoutes(callback) { } } -var serviceWatches = [] +const serviceWatches = [] const startWatchServices = function () { serviceWatch.watch( `/api/v1/namespaces/${namespace}/services`, {}, - (type, apiObj, watchObj) => { + (type, apiObj, _watchObj) => { for (const callback of serviceWatches) { callback(type, apiObj) } @@ -661,13 +666,13 @@ export function WatchServices(callback) { } } -var podWatches = [] +const podWatches = [] const startWatchPods = function () { podWatch.watch( `/api/v1/namespaces/${namespace}/pods`, {}, - (type, apiObj, watchObj) => { + (type, apiObj, _watchObj) => { for (const callback of podWatches) { callback(type, apiObj) } @@ -689,19 +694,19 @@ export function WatchPods(callback) { } } -var routerAccessWatches = {} // {namespace => list of watches} +const routerAccessWatches = {} // {namespace => list of watches} const startWatchRouterAccesses = function (ns) { routerAccessWatch.watch( `/apis/skupper.io/v2alpha1/namespaces/${ns}/routeraccesses`, {}, - (type, apiObj, watchObj) => { + (type, apiObj, _watchObj) => { const toDelete = []; for (const callback of routerAccessWatches[ns]) { if (callback(type, apiObj) === 'cancel') { toDelete.push(callback); } } - routerAccessWatches[ns] = routerAccessWatches[ns].filter(item => toDelete.indexOf(item) == -1); + routerAccessWatches[ns] = routerAccessWatches[ns].filter(item => !toDelete.includes(item)); }, (err) => { if (err) { @@ -729,12 +734,12 @@ export function startWatchRouterAccessesFn(callback, ns) { // Keep the old export name for compatibility export { startWatchRouterAccessesFn as startWatchRouterAccesses } -var networkAccessWatches = [] +const networkAccessWatches = [] export function startWatchNetworkAccesses() { networkAccessWatch.watch( `/apis/skupper.io/v2alpha1/namespaces/${namespace}/networkaccesses`, {}, - (type, apiObj, watchObj) => { + (type, apiObj, _watchObj) => { for (const callback of networkAccessWatches) { callback(type, apiObj) } @@ -791,6 +796,6 @@ const logWatchErrors = function () { export async function ApplyYaml(yaml) { setTimeout(logWatchErrors, 60 * 1000) // TODO - Check this. It's probably not right - let obj = YAML.parse(yaml) + const obj = YAML.parse(yaml) return await ApplyObject(obj) } diff --git a/modules/src/log.js b/modules/src/log.js index 6b2895c7..0fe0bdfd 100644 --- a/modules/src/log.js +++ b/modules/src/log.js @@ -20,8 +20,8 @@ import util from "node:util" export function Log(thing) { - let now = new Date().toISOString() - var text + const now = new Date().toISOString() + let text if (typeof thing == "string") { text = util.format("%s", thing) } else { diff --git a/modules/src/protocol.js b/modules/src/protocol.js index 2a644195..03884b8b 100644 --- a/modules/src/protocol.js +++ b/modules/src/protocol.js @@ -23,7 +23,7 @@ const OP_GET = "GET" const OP_CLAIM = "CLAIM" export function Heartbeat(fromSite, fromClass, hashSet, sequence, address = "") { - let body = { + const body = { version: VERSION, op: OP_HEARTBEAT, site: fromSite, @@ -32,7 +32,7 @@ export function Heartbeat(fromSite, fromClass, hashSet, sequence, address = "") address: address, } - if (!!hashSet) { + if (hashSet) { body.hashset = hashSet } @@ -88,12 +88,12 @@ export function SourceSite(body) { if (body.op == OP_HEARTBEAT || body.op == OP_GET) { return body.site } - throw Error("Can not determine source site-id from message") + throw new Error("Can not determine source site-id from message") } export async function DispatchMessage(body, onHeartbeat, onGet, onClaim) { if (body.version != VERSION) { - throw Error(`Unsupported protocol version ${body.version}`) + throw new Error(`Unsupported protocol version ${body.version}`) } switch (body.op) { @@ -107,6 +107,6 @@ export async function DispatchMessage(body, onHeartbeat, onGet, onClaim) { await onClaim(body.claim, body.name) break default: - throw Error(`Unknown op-code ${body.op}`) + throw new Error(`Unknown op-code ${body.op}`) } } diff --git a/modules/src/router.js b/modules/src/router.js index 1c421bba..d8dfe300 100644 --- a/modules/src/router.js +++ b/modules/src/router.js @@ -22,10 +22,10 @@ import { OpenSender, Request } from "./amqp.js"; const QUERY_TIMEOUT_SECONDS = 5; function convertBodyToItems(body) { - let keys = body.attributeNames; - let items = []; + const keys = body.attributeNames; + const items = []; body.results.forEach((values) => { - let item = {}; + const item = {}; for (let i = 0; i < keys.length; i++) { item[keys[i]] = values[i]; } @@ -48,13 +48,13 @@ export class RouterManagement { async _listManagementEntity(entityType, timeout, attributes = []) { if (this.ready) { - let requestAp = { + const requestAp = { operation : "QUERY", type : "org.amqp.management", entityType : entityType, name : "self", }; - let requestBody = { + const requestBody = { attributeNames : attributes, }; @@ -70,7 +70,7 @@ export class RouterManagement { } async _createManagementEntity(entityType, name, data, timeout) { - let requestAp = { + const requestAp = { operation : "CREATE", type : entityType, name : name, @@ -85,7 +85,7 @@ export class RouterManagement { } async _deleteManagementEntity(entityType, name, timeout) { - let requestAp = { + const requestAp = { operation : "DELETE", type : entityType, name : name, diff --git a/modules/src/state-sync.js b/modules/src/state-sync.js index c743ab82..9566b362 100644 --- a/modules/src/state-sync.js +++ b/modules/src/state-sync.js @@ -46,7 +46,6 @@ let localAddress let addressToUse let initialBeacon = true let onNewPeer -let onPeerLost let onStateChange let onStateRequest let onPing @@ -81,13 +80,13 @@ function timerDelayMsec(floorSec) { } function sendHeartbeat(peerId) { - let peer = peers[peerId] - if (!!peer) { + const peer = peers[peerId] + if (peer) { if (peer.hbTimer) { clearTimeout(peer.hbTimer) } const sender = connections[peer.connectionKey]?.apiSender - if (!!sender) { + if (sender) { const message = protocol.Heartbeat( localId, localClass, @@ -155,7 +154,7 @@ async function onHeartbeat(connectionKey, peerClass, peerId, hashset, sequence, // // If the hashset is not present in the heartbeat, there is no synchronization to be done. // - if (!!hashset) { + if (hashset) { //Log('Current Hashset:'); //Log(peers[peerId].remoteState); //Log('Heartbeat Hashset:'); @@ -163,8 +162,8 @@ async function onHeartbeat(connectionKey, peerClass, peerId, hashset, sequence, // // Reconcile the existing remote state against the advertized remote state. // - let toRequestStateKeys = [] - let toDeleteStateKeys = {} + const toRequestStateKeys = [] + const toDeleteStateKeys = {} for (const key of Object.keys(peers[peerId].remoteState)) { toDeleteStateKeys[key] = true } @@ -197,7 +196,7 @@ async function onHeartbeat(connectionKey, peerClass, peerId, hashset, sequence, for (const key of toRequestStateKeys) { try { Log(`SYNC: Requesting state update for key: ${key}, to: ${peers[peerId].address}`) - const [ap, body] = await amqp.Request( + const [_ap, body] = await amqp.Request( sender, protocol.GetState(localId, key), {}, @@ -245,7 +244,7 @@ function sendInitialBeacon() { } } -function onSendable(connectionKey) { +function onSendable(_connectionKey) { if (initialBeacon) { sendInitialBeacon() } @@ -274,7 +273,7 @@ async function processMessage(connectionKey, body, onReply) { const [hash, data] = await onStateRequest(site, statekey) onReply({}, protocol.GetStateResponseSuccess(statekey, hash, data)) }, - async (claimId, name) => { + async (_claimId, _name) => { // onClaim } ) @@ -360,7 +359,7 @@ export async function AddConnection(key, conn) { throw new Error(error) } - let connRecord = { + const connRecord = { conn: conn, apiSender: amqp.OpenSender( "AnonymousSender", @@ -372,7 +371,7 @@ export async function AddConnection(key, conn) { apiReceiver: null, } - if (!!localAddress) { + if (localAddress) { connRecord.apiReceiver = amqp.OpenReceiver( conn, localAddress, @@ -439,7 +438,6 @@ export async function Start( localId = _id localAddress = _address onNewPeer = _onNewPeer - onPeerLost = _onPeerLost onStateChange = _onStateChange onStateRequest = _onStateRequest onPing = _onPing diff --git a/modules/src/util.js b/modules/src/util.js index 00407a47..d27c1d28 100644 --- a/modules/src/util.js +++ b/modules/src/util.js @@ -24,15 +24,14 @@ const mapEqual_sync = function (left, right) { return left === right } - let leftKeys = Object.keys(left) - let rightKeys = Object.keys(right) + const leftKeys = Object.keys(left) + const rightKeys = Object.keys(right) if (leftKeys.length != rightKeys.length) { return false } - var i - for (i = 0; i < leftKeys.length; i++) { - let key = leftKeys[i] + for (let i = 0; i < leftKeys.length; i++) { + const key = leftKeys[i] if (!rightKeys.includes(key)) { return false } @@ -47,8 +46,8 @@ const mapEqual_sync = function (left, right) { export { mapEqual_sync } export function allSettled(plist) { - return new Promise((resolve, reject) => { - let results = [] + return new Promise((resolve) => { + const results = [] if (plist.length == 0) { resolve(results) } else { @@ -79,7 +78,7 @@ export function allSettled(plist) { const uuidRegex = RegExp( "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}", ) -const dnsRegex = RegExp("^[A-Za-z][A-Za-z0-9-\.]{0,63}$") +const dnsRegex = RegExp("^[A-Za-z][A-Za-z0-9-.]{0,63}$") const dnsSegmentRegex = RegExp("^[a-z][a-z0-9-]{0,63}$") const dtzRegex = RegExp( "^[1-2][0-9]{3}-[0-1][0-9]-[0-3][0-9]T[0-2][0-9]:[0-5][0-9]:[0-5][0-9].[0-9]{3}Z$", @@ -90,25 +89,25 @@ export function IsValidUuid(text) { } export function ValidateAndNormalizeFields(fields, table) { - var optional = {} + const optional = {} for (const [key, value] of Object.entries(table)) { optional[key] = value.optional } - var normalized = {} + const normalized = {} for (const [key, value] of Object.entries(fields)) { - if (Object.keys(table).indexOf(key) < 0) { - throw Error(`Unknown field key ${key}`) + if (!Object.keys(table).includes(key)) { + throw new Error(`Unknown field key ${key}`) } delete optional[key] switch (table[key].type) { case "string": if (typeof value != "string") { - throw Error(`Expected string value for ${key}`) + throw new TypeError(`Expected string value for ${key}`) } - if (value.indexOf("'") != -1) { - throw Error(`Single quotes not permitted for ${key}`) + if (value.includes("'")) { + throw new Error(`Single quotes not permitted for ${key}`) } normalized[key] = value break @@ -117,7 +116,7 @@ export function ValidateAndNormalizeFields(fields, table) { if (dnsRegex.test(value)) { normalized[key] = value } else { - throw Error( + throw new Error( `Expected valid DNS-name syntax for ${key} (got '${value}')`, ) } @@ -127,7 +126,7 @@ export function ValidateAndNormalizeFields(fields, table) { if (dnsSegmentRegex.test(value)) { normalized[key] = value } else { - throw Error( + throw new Error( `Expected valid DNS-segment syntax for ${key} (got '${value}')`, ) } @@ -143,16 +142,16 @@ export function ValidateAndNormalizeFields(fields, table) { ) { normalized[key] = value } else { - throw Error(`Expected [claim, peer, member, manage, van] for ${key}`) + throw new Error(`Expected [claim, peer, member, manage, van] for ${key}`) } break case "kubeselector": - throw Error(`kubeselector field type not implemented, got ${value}`) + throw new Error(`kubeselector field type not implemented, got ${value}`) case "bool": if (typeof value != "string" || (value != "true" && value != "false")) { - throw Error(`Expected [true, false] for ${key}`) + throw new Error(`Expected [true, false] for ${key}`) } normalized[key] = value == "true"; break @@ -160,13 +159,13 @@ export function ValidateAndNormalizeFields(fields, table) { case "number": if (typeof value == "string") { if (isNaN(value)) { - throw Error(`String value is not numeric for ${key}`) + throw new TypeError(`String value is not numeric for ${key}`) } normalized[key] = parseInt(value) } else if (typeof value == "number") { normalized[key] = value } else { - throw Error(`Expected a number or numeric string for ${key}`) + throw new TypeError(`Expected a number or numeric string for ${key}`) } break @@ -174,13 +173,13 @@ export function ValidateAndNormalizeFields(fields, table) { if (dtzRegex.test(value)) { normalized[key] = value } else { - throw Error(`timestampz field malformed: ${value}`) + throw new Error(`timestampz field malformed: ${value}`) } break case "uuid": if (!IsValidUuid(value)) { - throw Error(`Expected valid uuid for ${key}`) + throw new Error(`Expected valid uuid for ${key}`) } normalized[key] = value } @@ -188,7 +187,7 @@ export function ValidateAndNormalizeFields(fields, table) { for (const [key, value] of Object.entries(optional)) { if (!value) { - throw Error(`Mandatory key ${key} not found`) + throw new Error(`Mandatory key ${key} not found`) } else { normalized[key] = table[key].default } @@ -198,12 +197,12 @@ export function ValidateAndNormalizeFields(fields, table) { } export function UniquifyName(name, existingNames) { - if (existingNames.indexOf(name) < 0) { + if (!existingNames.includes(name)) { return name } - var ordinal = 2 - while (existingNames.indexOf(`${name}.${ordinal}`) >= 0) { + let ordinal = 2 + while (existingNames.includes(`${name}.${ordinal}`)) { ordinal++ } return `${name}.${ordinal}` diff --git a/tests/integration/helpers/postgres.js b/tests/integration/helpers/postgres.js index 843d17f5..f8882d4b 100644 --- a/tests/integration/helpers/postgres.js +++ b/tests/integration/helpers/postgres.js @@ -37,7 +37,7 @@ export function getPostgresPassword() { /** Escape a string for use inside single-quoted bash argument. */ function shellSingleQuote(value) { - return `'${String(value).replace(/'/g, `'\"'\"'`)}'`; + return `'${String(value).replaceAll("'", "'\"'\"'")}'`; } /** diff --git a/tests/integration/kind/specs/mgmt-health.test.js b/tests/integration/kind/specs/mgmt-health.test.js index 36626357..1150bc21 100644 --- a/tests/integration/kind/specs/mgmt-health.test.js +++ b/tests/integration/kind/specs/mgmt-health.test.js @@ -78,9 +78,8 @@ describe('management stack health', () => { ], { allowFailure: true }, ); - if (status === 0 && waitingReason) { - expect(['CrashLoopBackOff', 'Error', 'ImagePullBackOff']).not.toContain(waitingReason); - } + const relevantWaitingReason = status === 0 && waitingReason ? waitingReason : ''; + expect(['CrashLoopBackOff', 'Error', 'ImagePullBackOff']).not.toContain(relevantWaitingReason); }); it('management-controller startup log markers are present', () => {