From 0211594372f65315900aa73963f1d5bc467602a3 Mon Sep 17 00:00:00 2001 From: Brant Burnett Date: Thu, 21 Dec 2023 21:30:06 +0000 Subject: [PATCH] Match secure port numbers Motivation ---------- Couchbase Capella uses port 18091 to represent index nodes, but we normalize to port 8091 to compare the node list if no port is specified. Modifications ------------- When connecting via the "couchbases" secure protocol, assume that index nodes use 18091 when normalizing. --- .../app/connection-manager.ts | 2 +- .../app/definition/index-definition.spec.ts | 140 +++++++++++++----- .../app/definition/index-definition.ts | 27 ++-- .../app/index-manager.ts | 3 +- packages/couchbase-index-manager/app/sync.ts | 1 + 5 files changed, 119 insertions(+), 54 deletions(-) diff --git a/packages/couchbase-index-manager/app/connection-manager.ts b/packages/couchbase-index-manager/app/connection-manager.ts index ed75a6f..01e7670 100644 --- a/packages/couchbase-index-manager/app/connection-manager.ts +++ b/packages/couchbase-index-manager/app/connection-manager.ts @@ -44,7 +44,7 @@ export class ConnectionManager { this.bucket = this.cluster.bucket(this.connectionInfo.bucketName); - return new IndexManager(this.bucket, this.cluster); + return new IndexManager(this.bucket, this.cluster, this.connectionInfo.cluster.startsWith("couchbases://")); } /** diff --git a/packages/couchbase-index-manager/app/definition/index-definition.spec.ts b/packages/couchbase-index-manager/app/definition/index-definition.spec.ts index 7a3f8d5..7c29eea 100644 --- a/packages/couchbase-index-manager/app/definition/index-definition.spec.ts +++ b/packages/couchbase-index-manager/app/definition/index-definition.spec.ts @@ -513,6 +513,7 @@ describe('getMutation partition change', function() { nodes: ['a:8091'], }), ], + isSecure: false, })]; expect(mutations).toHaveLength(0); @@ -538,6 +539,7 @@ describe('getMutation partition change', function() { nodes: ['a:8091'], }, ].map(fakeIndex), + isSecure: false, })]; expect(mutations).toHaveLength(0); @@ -562,6 +564,7 @@ describe('getMutation partition change', function() { nodes: ['a:8091'], }, ].map(fakeIndex), + isSecure: false, })]; expect(mutations).toHaveLength(0); @@ -585,6 +588,7 @@ describe('getMutation partition change', function() { nodes: ['a:8091'], }, ].map(fakeIndex), + isSecure: false, })]; expect(mutations).toHaveLength(1); @@ -611,6 +615,7 @@ describe('getMutation partition change', function() { nodes: ['a:8091'], }, ].map(fakeIndex), + isSecure: false, })]; expect(mutations).toHaveLength(1); @@ -632,6 +637,7 @@ describe('getMutation partition change', function() { nodes: ['a:8091'], }, ].map(fakeIndex), + isSecure: false, })]; expect(mutations).toHaveLength(1); @@ -655,6 +661,7 @@ describe('getMutation partition change', function() { nodes: ['a:8091'], }, ].map(fakeIndex), + isSecure: false, })]; expect(mutations).toHaveLength(1); @@ -684,6 +691,7 @@ describe('getMutation manual replica node changes', function() { nodes: ['c:8091'], }, ].map(fakeIndex), + isSecure: false, })]; expect(mutations).toHaveLength(1); @@ -716,6 +724,7 @@ describe('getMutation manual replica node changes', function() { nodes: ['a:8091'], }, ].map(fakeIndex), + isSecure: false, })]; expect(mutations).toHaveLength(0); @@ -737,6 +746,7 @@ describe('getMutation manual replica node changes', function() { nodes: ['d:8091'], }, ].map(fakeIndex), + isSecure: false, })]; expect(mutations).toHaveLength(3); @@ -776,6 +786,7 @@ describe('getMutation automatic replica node changes', function() { num_replica: 1, }, ].map(fakeIndex), + isSecure: false, clusterVersion: { major: 5, minor: 5, @@ -806,6 +817,7 @@ describe('getMutation automatic replica node changes', function() { num_replica: 1, }, ].map(fakeIndex), + isSecure: false, clusterVersion: { major: 5, minor: 5, @@ -831,6 +843,7 @@ describe('getMutation automatic replica node changes', function() { num_replica: 1, }, ].map(fakeIndex), + isSecure: false, clusterVersion: { major: 5, minor: 5, @@ -862,6 +875,7 @@ describe('getMutation automatic replica node changes', function() { num_replica: 0, }, ].map(fakeIndex), + isSecure: false, clusterVersion: { major: 5, minor: 5, @@ -893,6 +907,7 @@ describe('getMutation automatic replica node changes', function() { num_replica: 1, }, ].map(fakeIndex), + isSecure: false, clusterVersion: { major: 6, minor: 5, @@ -924,6 +939,7 @@ describe('getMutation automatic replica node changes', function() { num_replica: 0, }, ].map(fakeIndex), + isSecure: false, clusterVersion: { major: 6, minor: 5, @@ -959,6 +975,7 @@ describe('getMutation automatic replica node changes', function() { partition: 'HASH(`type`)', }, ].map(fakeIndex), + isSecure: false, clusterVersion: { major: 5, minor: 5, @@ -990,6 +1007,7 @@ describe('getMutation automatic replica node changes', function() { num_replica: 1, }, ].map(fakeIndex), + isSecure: false, clusterVersion: { major: 5, minor: 5, @@ -1021,6 +1039,7 @@ describe('getMutation automatic replica node changes', function() { num_replica: 1, }, ].map(fakeIndex), + isSecure: false, clusterVersion: { major: 6, minor: 5, @@ -1052,7 +1071,8 @@ describe('getMutation scope/collection', function() { index_key: ['`key`'], nodes: ['a:8091'] }, - ].map(fakeIndex) + ].map(fakeIndex), + isSecure: false, })]; expect(mutations).toHaveLength(0); @@ -1074,7 +1094,8 @@ describe('getMutation scope/collection', function() { index_key: ['`key`'], nodes: ['a:8091'] }, - ].map(fakeIndex) + ].map(fakeIndex), + isSecure: false, })]; expect(mutations).toHaveLength(1); @@ -1091,7 +1112,10 @@ describe('normalizeNodeList', function() { nodes: ['b', 'c', 'a'], }); - def.normalizeNodeList([]); + def.normalizeNodeList({ + currentIndexes: [], + isSecure: false, + }); expect(def.nodes) .toStrictEqual(['a:8091', 'b:8091', 'c:8091']); @@ -1104,12 +1128,31 @@ describe('normalizeNodeList', function() { nodes: ['a', 'b', 'c'], }); - def.normalizeNodeList([]); + def.normalizeNodeList({ + currentIndexes: [], + isSecure: false, + }); expect(def.nodes) .toStrictEqual(['a:8091', 'b:8091', 'c:8091']); }); + it('adds secure port numbers', function() { + const def = new IndexDefinition({ + name: 'test', + index_key: 'key', + nodes: ['a', 'b', 'c'], + }); + + def.normalizeNodeList({ + currentIndexes: [], + isSecure: true, + }); + + expect(def.nodes) + .toStrictEqual(['a:18091', 'b:18091', 'c:18091']); + }); + it('ignores defined port numbers', function() { const def = new IndexDefinition({ name: 'test', @@ -1117,7 +1160,10 @@ describe('normalizeNodeList', function() { nodes: ['a:18091', 'b', 'c'], }); - def.normalizeNodeList([]); + def.normalizeNodeList({ + currentIndexes: [], + isSecure: false, + }); expect(def.nodes) .toStrictEqual(['a:18091', 'b:8091', 'c:8091']); @@ -1133,7 +1179,10 @@ describe('normalizeNodeList', function() { nodes: ['b', 'c', 'a'], }); - def.normalizeNodeList([]); + def.normalizeNodeList({ + currentIndexes: [], + isSecure: false, + }); expect(def.nodes) .toStrictEqual(['a:8091', 'b:8091', 'c:8091']); @@ -1147,7 +1196,10 @@ describe('normalizeNodeList', function() { nodes: ['a', 'b', 'c'], }); - def.normalizeNodeList([]); + def.normalizeNodeList({ + currentIndexes: [], + isSecure: false, + }); expect(def.nodes) .toStrictEqual(['a:8091', 'b:8091', 'c:8091']); @@ -1161,7 +1213,10 @@ describe('normalizeNodeList', function() { nodes: ['a:18091', 'b', 'c'], }); - def.normalizeNodeList([]); + def.normalizeNodeList({ + currentIndexes: [], + isSecure: false, + }); expect(def.nodes) .toStrictEqual(['a:18091', 'b:8091', 'c:8091']); @@ -1175,20 +1230,23 @@ describe('normalizeNodeList', function() { nodes: ['a', 'b', 'c'], }); - def.normalizeNodeList([ - { - name: 'test', - nodes: ['b:8091'], - }, - { - name: 'test_replica1', - nodes: ['c:8091'], - }, - { - name: 'test_replica2', - nodes: ['a:8091'], - }, - ].map(fakeIndex)); + def.normalizeNodeList({ + currentIndexes: [ + { + name: 'test', + nodes: ['b:8091'], + }, + { + name: 'test_replica1', + nodes: ['c:8091'], + }, + { + name: 'test_replica2', + nodes: ['a:8091'], + }, + ].map(fakeIndex), + isSecure: false, + }); expect(def.nodes) .toStrictEqual(['b:8091', 'c:8091', 'a:8091']); @@ -1202,12 +1260,15 @@ describe('normalizeNodeList', function() { nodes: ['a', 'b', 'c'], }); - def.normalizeNodeList([ - { - name: 'test', - nodes: ['b:8091'], - }, - ].map(fakeIndex)); + def.normalizeNodeList({ + currentIndexes: [ + { + name: 'test', + nodes: ['b:8091'], + }, + ].map(fakeIndex), + isSecure: false, + }); expect(def.nodes) .toStrictEqual(['b:8091', 'a:8091', 'c:8091']); @@ -1221,16 +1282,19 @@ describe('normalizeNodeList', function() { nodes: ['a', 'b', 'c'], }); - def.normalizeNodeList([ - { - name: 'test', - nodes: ['b:8091'], - }, - { - name: 'test_replica2', - nodes: ['a:8091'], - }, - ].map(fakeIndex)); + def.normalizeNodeList({ + currentIndexes: [ + { + name: 'test', + nodes: ['b:8091'], + }, + { + name: 'test_replica2', + nodes: ['a:8091'], + }, + ].map(fakeIndex), + isSecure: false, + }); expect(def.nodes) .toStrictEqual(['b:8091', 'c:8091', 'a:8091']); diff --git a/packages/couchbase-index-manager/app/definition/index-definition.ts b/packages/couchbase-index-manager/app/definition/index-definition.ts index 12fb195..a4faaf7 100644 --- a/packages/couchbase-index-manager/app/definition/index-definition.ts +++ b/packages/couchbase-index-manager/app/definition/index-definition.ts @@ -9,16 +9,17 @@ import { IndexDefinitionBase } from './index-definition-base'; export interface MutationContext { currentIndexes: CouchbaseIndex[]; clusterVersion?: Version; + isSecure?: boolean; } /** * Ensures that a server name has a port number appended, defaults to 8091 */ -function ensurePort(server: string): string { +function ensurePort(server: string, isSecure?: boolean): string { if (/:\d+$/.exec(server)) { return server; } else { - return server + ':8091'; + return server + (isSecure ? ':18091' : ':8091'); } } @@ -170,7 +171,7 @@ export class IndexDefinition extends IndexDefinitionBase implements IndexConfigu * Gets the required index mutations, if any, to sync this definition */ * getMutations(context: MutationContext): Iterable { - this.normalizeNodeList(context.currentIndexes); + this.normalizeNodeList(context); const mutations = []; @@ -210,13 +211,13 @@ export class IndexDefinition extends IndexDefinitionBase implements IndexConfigu // Index isn't found if (!drop) { yield new CreateIndexMutation(this, this.name + suffix, - this.getWithClause(replicaNum)); + this.getWithClause(context, replicaNum)); } } else if (drop) { yield new DropIndexMutation(this, currentIndex.name); } else if (!this.is_primary && this.requiresUpdate(currentIndex)) { yield new UpdateIndexMutation(this, this.name + suffix, - this.getWithClause(replicaNum), + this.getWithClause(context, replicaNum), currentIndex); } else if (!this.manual_replica && !_.isUndefined(currentIndex.num_replica) && @@ -228,7 +229,7 @@ export class IndexDefinition extends IndexDefinitionBase implements IndexConfigu yield new ResizeIndexMutation(this, this.name + suffix); } else { yield new UpdateIndexMutation(this, this.name + suffix, - this.getWithClause(replicaNum), + this.getWithClause(context, replicaNum), currentIndex); } } else if (this.nodes && currentIndex.nodes) { @@ -238,7 +239,7 @@ export class IndexDefinition extends IndexDefinitionBase implements IndexConfigu if (this.manual_replica) { if (this.nodes[replicaNum] !== currentIndex.nodes[0]) { yield new UpdateIndexMutation(this, this.name + suffix, - this.getWithClause(replicaNum), + this.getWithClause(context, replicaNum), currentIndex); } } else { @@ -249,17 +250,17 @@ export class IndexDefinition extends IndexDefinitionBase implements IndexConfigu } } - private getWithClause(replicaNum?: number): WithClause { + private getWithClause(context: MutationContext, replicaNum?: number): WithClause { let withClause: WithClause; if (!this.manual_replica) { withClause = { - nodes: this.nodes ? this.nodes.map(ensurePort) : undefined, + nodes: this.nodes ? this.nodes.map(p => ensurePort(p, context.isSecure)) : undefined, num_replica: this.num_replica, }; } else { withClause = { - nodes: this.nodes && [ensurePort(this.nodes[replicaNum ?? 0])], + nodes: this.nodes && [ensurePort(this.nodes[replicaNum ?? 0], context.isSecure)], }; } @@ -461,12 +462,12 @@ export class IndexDefinition extends IndexDefinitionBase implements IndexConfigu * order as the current indexes. This allows easy matching of existing * node assignments, reducing reindex load due to minor node shifts. */ - normalizeNodeList(currentIndexes: CouchbaseIndex[]): void { + normalizeNodeList(context: MutationContext): void { if (!this.nodes) { return; } - this.nodes = this.nodes.map(ensurePort); + this.nodes = this.nodes.map(p => ensurePort(p, context.isSecure)); this.nodes.sort(); if (this.manual_replica) { @@ -481,7 +482,7 @@ export class IndexDefinition extends IndexDefinitionBase implements IndexConfigu '' : `_replica${replicaNum}`; - const index = currentIndexes.find((index) => { + const index = context.currentIndexes.find((index) => { return this.isMatch(index, suffix); }); diff --git a/packages/couchbase-index-manager/app/index-manager.ts b/packages/couchbase-index-manager/app/index-manager.ts index 7222599..243f05c 100644 --- a/packages/couchbase-index-manager/app/index-manager.ts +++ b/packages/couchbase-index-manager/app/index-manager.ts @@ -143,7 +143,7 @@ export class IndexManager { * @param {Bucket} bucket * @param {Cluster} cluster */ - constructor(private bucket: Bucket, private cluster: Cluster) { + constructor(private bucket: Bucket, private cluster: Cluster, readonly isSecure: boolean = false) { this.bucket = bucket; this.cluster = cluster; this.manager = cluster.queryIndexes(); @@ -295,7 +295,6 @@ export class IndexManager { } const statement = this.getAlterStatement(indexName, scope, collection, withClause); - console.log(statement); await this.cluster.query(statement, {adhoc: true}); } diff --git a/packages/couchbase-index-manager/app/sync.ts b/packages/couchbase-index-manager/app/sync.ts index 6654366..cf198b1 100644 --- a/packages/couchbase-index-manager/app/sync.ts +++ b/packages/couchbase-index-manager/app/sync.ts @@ -70,6 +70,7 @@ export class Sync { const mutationContext = { currentIndexes: await this.manager.getIndexes(), clusterVersion: await this.manager.getClusterVersion(), + isSecure: this.manager.isSecure, }; // Normalize the definitions before testing for mutations