diff --git a/controlplane/src/bin/billing.json b/controlplane/src/bin/billing.json index 0c43fc9612..1cd6f345ac 100644 --- a/controlplane/src/bin/billing.json +++ b/controlplane/src/bin/billing.json @@ -28,6 +28,11 @@ { "id": "field-pruning-grace-period", "limit": 0 + }, + { + "id": "plugins", + "description": "3 Plugins", + "limit": 3 } ] }, @@ -72,8 +77,8 @@ }, { "id": "plugins", - "description": "3 Plugins", - "limit": 3 + "description": "10 Plugins", + "limit": 10 } ] }, @@ -124,8 +129,8 @@ }, { "id": "plugins", - "description": "15 Plugins", - "limit": 15 + "description": "20 Plugins", + "limit": 20 } ] }, @@ -173,7 +178,7 @@ { "id": "plugins", "description": "Unlimited Plugins", - "limit": 20 + "limit": 30 } ] } diff --git a/controlplane/test/feature-subgraph/create-feature-subgraph.test.ts b/controlplane/test/feature-subgraph/create-feature-subgraph.test.ts index db7f59ac93..661e5fe12e 100644 --- a/controlplane/test/feature-subgraph/create-feature-subgraph.test.ts +++ b/controlplane/test/feature-subgraph/create-feature-subgraph.test.ts @@ -418,7 +418,7 @@ describe('Create feature subgraph tests', () => { test('that creating a feature subgraph from a plugin base fails when plugin limit is reached', async () => { const { client, server } = await SetupTest({ dbname, - setupBilling: { plan: 'launch@1' }, // Launch plan allows max 3 plugins + setupBilling: { plan: 'developer@1' }, // Developer plan allows max 3 plugins }); const basePluginName = genID('basePlugin'); diff --git a/controlplane/test/plugin/validate-and-fetch-plugin-data.test.ts b/controlplane/test/plugin/validate-and-fetch-plugin-data.test.ts index 10f693de3f..41a931c862 100644 --- a/controlplane/test/plugin/validate-and-fetch-plugin-data.test.ts +++ b/controlplane/test/plugin/validate-and-fetch-plugin-data.test.ts @@ -137,13 +137,28 @@ describe('ValidateAndFetchPluginData', () => { setupBilling: { plan: 'developer@1' }, // Developer plan has 0 plugin limit }); - const pluginName = genID('plugin'); - const label = genUniqueLabel('test'); + // Create 3 plugins successfully + for (let i = 1; i <= 3; i++) { + const pluginName = genID(`plugin-${i}`); + const pluginLabel = genUniqueLabel(`team-${i}`); + + const createPluginSubgraphResp = await client.createFederatedSubgraph({ + name: pluginName, + namespace: DEFAULT_NAMESPACE, + type: SubgraphType.GRPC_PLUGIN, + labels: [pluginLabel], + }); + + expect(createPluginSubgraphResp.response?.code).toBe(EnumStatusCode.OK); + } + + const fourthPluginName = genID('plugin-4'); + const fourthPluginLabel = genUniqueLabel('team-4'); const response = await client.validateAndFetchPluginData({ - name: pluginName, + name: fourthPluginName, namespace: DEFAULT_NAMESPACE, - labels: [label], + labels: [fourthPluginLabel], }); expect(response.response?.code).toBe(EnumStatusCode.ERR_LIMIT_REACHED); diff --git a/controlplane/test/subgraph/create-subgraph.test.ts b/controlplane/test/subgraph/create-subgraph.test.ts index 9cd240984a..86bdee355a 100644 --- a/controlplane/test/subgraph/create-subgraph.test.ts +++ b/controlplane/test/subgraph/create-subgraph.test.ts @@ -575,30 +575,45 @@ describe('Create subgraph tests', () => { setupBilling: { plan: 'developer@1' }, }); - const pluginName = genID('plugin'); - const pluginLabel = genUniqueLabel('env'); + // Create 3 plugins successfully + for (let i = 1; i <= 3; i++) { + const pluginName = genID(`plugin-${i}`); + const pluginLabel = genUniqueLabel(`team-${i}`); - const createPluginSubgraphResp = await client.createFederatedSubgraph({ - name: pluginName, + const createPluginSubgraphResp = await client.createFederatedSubgraph({ + name: pluginName, + namespace: DEFAULT_NAMESPACE, + type: SubgraphType.GRPC_PLUGIN, + labels: [pluginLabel], + }); + + expect(createPluginSubgraphResp.response?.code).toBe(EnumStatusCode.OK); + } + + const fourthPluginName = genID('plugin-4'); + const fourthPluginLabel = genUniqueLabel('team-4'); + + const createFourthPluginResponse = await client.createFederatedSubgraph({ + name: fourthPluginName, namespace: DEFAULT_NAMESPACE, type: SubgraphType.GRPC_PLUGIN, - labels: [pluginLabel], + labels: [fourthPluginLabel], }); - expect(createPluginSubgraphResp.response?.code).toBe(EnumStatusCode.ERR_LIMIT_REACHED); - expect(createPluginSubgraphResp.response?.details).toBe('The organization reached the limit of plugins'); + expect(createFourthPluginResponse.response?.code).toBe(EnumStatusCode.ERR_LIMIT_REACHED); + expect(createFourthPluginResponse.response?.details).toBe('The organization reached the limit of plugins'); await server.close(); }); - test('Should enforce plugin limit on launch plan (max 3 plugins)', async () => { + test('Should enforce plugin limit on launch plan (max 10 plugins)', async () => { const { client, server } = await SetupTest({ dbname, setupBilling: { plan: 'launch@1' }, }); - // Create 3 plugins successfully - for (let i = 1; i <= 3; i++) { + // Create 10 plugins successfully + for (let i = 1; i <= 10; i++) { const pluginName = genID(`plugin-${i}`); const pluginLabel = genUniqueLabel(`team-${i}`); @@ -612,19 +627,19 @@ describe('Create subgraph tests', () => { expect(createPluginSubgraphResp.response?.code).toBe(EnumStatusCode.OK); } - // The 4th plugin should fail due to limit - const fourthPluginName = genID('plugin-4'); - const fourthPluginLabel = genUniqueLabel('team-4'); + // The 11th plugin should fail due to limit + const eleventhPluginName = genID('plugin-11'); + const eleventhPluginLabel = genUniqueLabel('team-11'); - const createFourthPluginResp = await client.createFederatedSubgraph({ - name: fourthPluginName, + const createEleventhPluginResp = await client.createFederatedSubgraph({ + name: eleventhPluginName, namespace: DEFAULT_NAMESPACE, type: SubgraphType.GRPC_PLUGIN, - labels: [fourthPluginLabel], + labels: [eleventhPluginLabel], }); - expect(createFourthPluginResp.response?.code).toBe(EnumStatusCode.ERR_LIMIT_REACHED); - expect(createFourthPluginResp.response?.details).toBe('The organization reached the limit of plugins'); + expect(createEleventhPluginResp.response?.code).toBe(EnumStatusCode.ERR_LIMIT_REACHED); + expect(createEleventhPluginResp.response?.details).toBe('The organization reached the limit of plugins'); await server.close(); }); @@ -798,8 +813,8 @@ describe('Create subgraph tests', () => { setupBilling: { plan: 'launch@1' }, }); - // First, create the maximum number of plugins (3 for launch plan) - for (let i = 1; i <= 3; i++) { + // First, create the maximum number of plugins (10 for launch plan) + for (let i = 1; i <= 10; i++) { const pluginName = genID(`plugin-${i}`); const pluginLabel = genUniqueLabel(`plugin-${i}`); diff --git a/controlplane/test/subgraph/publish-subgraph.test.ts b/controlplane/test/subgraph/publish-subgraph.test.ts index bd25b8a935..0e868fd246 100644 --- a/controlplane/test/subgraph/publish-subgraph.test.ts +++ b/controlplane/test/subgraph/publish-subgraph.test.ts @@ -12,7 +12,7 @@ import { genID, genUniqueLabel, } from '../../src/core/test-util.js'; -import { createEventDrivenGraph, createSubgraph, eventDrivenGraphSDL, SetupTest, subgraphSDL } from '../test-util.js'; +import { createEventDrivenGraph, createSubgraph, DEFAULT_NAMESPACE, eventDrivenGraphSDL, SetupTest, subgraphSDL } from '../test-util.js'; // Read the actual proto, mapping and lock files const testDataPath = path.join(process.cwd(), 'test/test-data/plugin'); @@ -476,14 +476,29 @@ describe('Publish subgraph tests', () => { test('Should enforce plugin limits when creating plugin via publish', async () => { const { client, server } = await SetupTest({ dbname, - setupBilling: { plan: 'developer@1' }, // Developer plan has 0 plugin limit + setupBilling: { plan: 'developer@1' }, // Developer plan has 3 plugin limit }); - const pluginName = genID('plugin'); + // Create 3 plugins successfully + for (let i = 1; i <= 3; i++) { + const pluginName = genID(`plugin-${i}`); + const pluginLabel = genUniqueLabel(`team-${i}`); + + const createPluginSubgraphResp = await client.createFederatedSubgraph({ + name: pluginName, + namespace: DEFAULT_NAMESPACE, + type: SubgraphType.GRPC_PLUGIN, + labels: [pluginLabel], + }); + + expect(createPluginSubgraphResp.response?.code).toBe(EnumStatusCode.OK); + } + + const fourthPluginName = genID('plugin-4'); // Try to publish to a non-existent plugin subgraph on developer plan const publishResponse = await client.publishFederatedSubgraph({ - name: pluginName, + name: fourthPluginName, namespace: 'default', schema: pluginSDL, type: SubgraphType.GRPC_PLUGIN,