Skip to content

Commit

Permalink
fix: return error if the namespace doesnt exist while listing graphs (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
JivusAyrus authored Sep 24, 2024
1 parent ba52250 commit 3bc8035
Show file tree
Hide file tree
Showing 5 changed files with 461 additions and 19 deletions.
81 changes: 68 additions & 13 deletions controlplane/src/core/bufservices/PlatformService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8422,19 +8422,33 @@ export default function (opts: RouterOptions): Partial<ServiceImpl<typeof Platfo
const repo = new SubgraphRepository(logger, opts.db, authContext.organizationId);
const namespaceRepo = new NamespaceRepository(opts.db, authContext.organizationId);

let namespaceId: string | undefined;
// Namespace is optional, if not provided, we get all the subgraphs
const namespace = await namespaceRepo.byName(req.namespace);
if (req.namespace) {
const namespace = await namespaceRepo.byName(req.namespace);
if (!namespace) {
return {
response: {
code: EnumStatusCode.ERR_NOT_FOUND,
details: `Could not find namespace ${req.namespace}`,
},
graphs: [],
count: 0,
};
}
namespaceId = namespace.id;
}

const list: SubgraphDTO[] = await repo.list({
limit: req.limit,
offset: req.offset,
namespaceId: namespace?.id,
namespaceId,
query: req.query,
excludeFeatureSubgraphs: req.excludeFeatureSubgraphs,
});

const count = await repo.count({
namespaceId: namespace?.id,
namespaceId,
query: req.query,
limit: 0,
offset: 0,
Expand Down Expand Up @@ -8475,18 +8489,32 @@ export default function (opts: RouterOptions): Partial<ServiceImpl<typeof Platfo
const featureFlagRepo = new FeatureFlagRepository(logger, opts.db, authContext.organizationId);
const namespaceRepo = new NamespaceRepository(opts.db, authContext.organizationId);

// Namespace is optional, if not provided, we get all the subgraphs
const namespace = await namespaceRepo.byName(req.namespace);
let namespaceId: string | undefined;
// Namespace is optional, if not provided, we get all the feature subgraphs
if (req.namespace) {
const namespace = await namespaceRepo.byName(req.namespace);
if (!namespace) {
return {
response: {
code: EnumStatusCode.ERR_NOT_FOUND,
details: `Could not find namespace ${req.namespace}`,
},
featureSubgraphs: [],
count: 0,
};
}
namespaceId = namespace.id;
}

const list = await featureFlagRepo.getFeatureSubgraphs({
limit: req.limit,
offset: req.offset,
namespaceId: namespace?.id,
namespaceId,
query: req.query,
});

const count = await featureFlagRepo.getFeatureSubgraphsCount({
namespaceId: namespace?.id,
namespaceId,
query: req.query,
limit: 0,
offset: 0,
Expand Down Expand Up @@ -8575,13 +8603,26 @@ export default function (opts: RouterOptions): Partial<ServiceImpl<typeof Platfo
const fedGraphRepo = new FederatedGraphRepository(logger, opts.db, authContext.organizationId);
const namespaceRepo = new NamespaceRepository(opts.db, authContext.organizationId);

let namespaceId: string | undefined;
// Namespace is optional, if not provided, we get all the federated graphs
const namespace = await namespaceRepo.byName(req.namespace);
if (req.namespace) {
const namespace = await namespaceRepo.byName(req.namespace);
if (!namespace) {
return {
response: {
code: EnumStatusCode.ERR_NOT_FOUND,
details: `Could not find namespace ${req.namespace}`,
},
graphs: [],
};
}
namespaceId = namespace.id;
}

const list: FederatedGraphDTO[] = await fedGraphRepo.list({
limit: req.limit,
offset: req.offset,
namespaceId: namespace?.id,
namespaceId,
supportsFederation: req.supportsFederation,
});

Expand Down Expand Up @@ -11687,17 +11728,31 @@ export default function (opts: RouterOptions): Partial<ServiceImpl<typeof Platfo
const featureFlagRepo = new FeatureFlagRepository(logger, opts.db, authContext.organizationId);
const namespaceRepo = new NamespaceRepository(opts.db, authContext.organizationId);

// Namespace is optional, if not provided, we get all the subgraphs
const namespace = await namespaceRepo.byName(req.namespace);
let namespaceId: string | undefined;
// Namespace is optional, if not provided, we get all the feature flags
if (req.namespace) {
const namespace = await namespaceRepo.byName(req.namespace);
if (!namespace) {
return {
response: {
code: EnumStatusCode.ERR_NOT_FOUND,
details: `Could not find namespace ${req.namespace}`,
},
featureFlags: [],
totalCount: 0,
};
}
namespaceId = namespace.id;
}

const featureFlags = await featureFlagRepo.getFeatureFlags({
limit: req.limit,
offset: req.offset,
namespaceId: namespace?.id,
namespaceId,
query: req.query,
});

const totalCount = await featureFlagRepo.getFeatureFlagsCount({ namespaceId: namespace?.id });
const totalCount = await featureFlagRepo.getFeatureFlagsCount({ namespaceId });

return {
response: {
Expand Down
115 changes: 115 additions & 0 deletions controlplane/test/feature-flag/get-feature-flags.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { EnumStatusCode } from '@wundergraph/cosmo-connect/dist/common/common_pb';
import { afterAll, beforeAll, describe, expect, test } from 'vitest';
import { afterAllSetup, beforeAllSetup, genID, genUniqueLabel } from '../../src/core/test-util.js';
import {
DEFAULT_SUBGRAPH_URL_ONE,
DEFAULT_SUBGRAPH_URL_TWO,
SetupTest,
createBaseAndFeatureSubgraph,
} from '../test-util.js';

let dbname = '';

describe('List feature flags', (ctx) => {
beforeAll(async () => {
dbname = await beforeAllSetup();
});

afterAll(async () => {
await afterAllSetup(dbname);
});

test('Should be able to list feature flags of different namespace', async (testContext) => {
const { client, server } = await SetupTest({ dbname });

const subgraphName = genID('subgraph');
const featureSubgraphName = genID('featureSubgraph');
const flagName = genID('flag');

const createNamespaceResp = await client.createNamespace({
name: 'prod',
});

expect(createNamespaceResp.response?.code).toBe(EnumStatusCode.OK);

await createBaseAndFeatureSubgraph(
client,
subgraphName,
featureSubgraphName,
DEFAULT_SUBGRAPH_URL_ONE,
DEFAULT_SUBGRAPH_URL_TWO,
);

await createBaseAndFeatureSubgraph(
client,
subgraphName,
featureSubgraphName,
DEFAULT_SUBGRAPH_URL_ONE,
DEFAULT_SUBGRAPH_URL_TWO,
'prod',
);

let featureFlagResponse = await client.createFeatureFlag({
name: flagName,
featureSubgraphNames: [featureSubgraphName],
isEnabled: true,
});

expect(featureFlagResponse.response?.code).toBe(EnumStatusCode.OK);

featureFlagResponse = await client.createFeatureFlag({
name: flagName,
featureSubgraphNames: [featureSubgraphName],
namespace: 'prod',
isEnabled: true,
});

expect(featureFlagResponse.response?.code).toBe(EnumStatusCode.OK);

// fetching feature flags from default namespace
let listFeatureFlagsResp = await client.getFeatureFlags({
namespace: 'default',
offset: 0,
// fetches all
limit: 0,
});

expect(listFeatureFlagsResp.response?.code).toBe(EnumStatusCode.OK);
expect(listFeatureFlagsResp.totalCount).toBe(1);

// fetching feature flags from prod namespace
listFeatureFlagsResp = await client.getFeatureFlags({
namespace: 'prod',
offset: 0,
// fetches all
limit: 0,
});

expect(listFeatureFlagsResp.response?.code).toBe(EnumStatusCode.OK);
expect(listFeatureFlagsResp.totalCount).toBe(1);

// fetching all feature flags
listFeatureFlagsResp = await client.getFeatureFlags({
offset: 0,
// fetches all
limit: 0,
});

expect(listFeatureFlagsResp.response?.code).toBe(EnumStatusCode.OK);
expect(listFeatureFlagsResp.totalCount).toBe(2);

// fetching feature flags from non-existing namespace
listFeatureFlagsResp = await client.getFeatureFlags({
// prod1 namespace does not exist
namespace: 'prod1',
offset: 0,
// fetches all
limit: 0,
});

expect(listFeatureFlagsResp.response?.code).toBe(EnumStatusCode.ERR_NOT_FOUND);
expect(listFeatureFlagsResp.response?.details).toBe(`Could not find namespace prod1`);

await server.close();
});
});
98 changes: 98 additions & 0 deletions controlplane/test/feature-subgraph/get-feature-subgraphs.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { EnumStatusCode } from '@wundergraph/cosmo-connect/dist/common/common_pb';
import { afterAll, beforeAll, describe, expect, test } from 'vitest';
import { afterAllSetup, beforeAllSetup, genID } from '../../src/core/test-util.js';
import {
DEFAULT_SUBGRAPH_URL_ONE,
DEFAULT_SUBGRAPH_URL_TWO,
SetupTest,
createBaseAndFeatureSubgraph,
} from '../test-util.js';

let dbname = '';

describe('List feature subgraphs', (ctx) => {
beforeAll(async () => {
dbname = await beforeAllSetup();
});

afterAll(async () => {
await afterAllSetup(dbname);
});

test('Should be able to list feature subgraphs of different namespace', async (testContext) => {
const { client, server } = await SetupTest({ dbname });

const subgraphName = genID('subgraph');
const featureSubgraphName = genID('featureSubgraph');
const flagName = genID('flag');

const createNamespaceResp = await client.createNamespace({
name: 'prod',
});

expect(createNamespaceResp.response?.code).toBe(EnumStatusCode.OK);

await createBaseAndFeatureSubgraph(
client,
subgraphName,
featureSubgraphName,
DEFAULT_SUBGRAPH_URL_ONE,
DEFAULT_SUBGRAPH_URL_TWO,
);

await createBaseAndFeatureSubgraph(
client,
subgraphName,
featureSubgraphName,
DEFAULT_SUBGRAPH_URL_ONE,
DEFAULT_SUBGRAPH_URL_TWO,
'prod',
);

// fetching feature subgraphs from default namespace
let listFeatureSubgraphsResp = await client.getFeatureSubgraphs({
namespace: 'default',
offset: 0,
// fetches all
limit: 0,
});

expect(listFeatureSubgraphsResp.response?.code).toBe(EnumStatusCode.OK);
expect(listFeatureSubgraphsResp.count).toBe(1);

// fetching feature subgraphs from prod namespace
listFeatureSubgraphsResp = await client.getFeatureSubgraphs({
namespace: 'prod',
offset: 0,
// fetches all
limit: 0,
});

expect(listFeatureSubgraphsResp.response?.code).toBe(EnumStatusCode.OK);
expect(listFeatureSubgraphsResp.count).toBe(1);

// fetching all feature subgraphs
listFeatureSubgraphsResp = await client.getFeatureSubgraphs({
offset: 0,
// fetches all
limit: 0,
});

expect(listFeatureSubgraphsResp.response?.code).toBe(EnumStatusCode.OK);
expect(listFeatureSubgraphsResp.count).toBe(2);

// fetching feature subgraphs from non-existing namespace
listFeatureSubgraphsResp = await client.getFeatureSubgraphs({
// prod1 namespace does not exist
namespace: 'prod1',
offset: 0,
// fetches all
limit: 0,
});

expect(listFeatureSubgraphsResp.response?.code).toBe(EnumStatusCode.ERR_NOT_FOUND);
expect(listFeatureSubgraphsResp.response?.details).toBe(`Could not find namespace prod1`);

await server.close();
});
});
Loading

0 comments on commit 3bc8035

Please sign in to comment.