Skip to content

Commit 450accf

Browse files
n1ru4lcoderabbitai[bot]
authored andcommitted
feat(usage): report with organization access tokens (#6538)
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
1 parent 748dc82 commit 450accf

36 files changed

+1625
-404
lines changed

deployment/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,8 @@ const usage = deployUsage({
160160
docker,
161161
environment,
162162
tokens,
163+
redis,
164+
postgres,
163165
kafka,
164166
dbMigrations,
165167
commerce,

deployment/services/usage.ts

Lines changed: 78 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import * as pulumi from '@pulumi/pulumi';
21
import { serviceLocalEndpoint } from '../utils/local-endpoint';
32
import { ServiceDeployment } from '../utils/service-deployment';
43
import { CommerceService } from './commerce';
@@ -7,6 +6,8 @@ import { Docker } from './docker';
76
import { Environment } from './environment';
87
import { Kafka } from './kafka';
98
import { Observability } from './observability';
9+
import { Postgres } from './postgres';
10+
import { Redis } from './redis';
1011
import { Sentry } from './sentry';
1112
import { Tokens } from './tokens';
1213

@@ -15,6 +16,8 @@ export type Usage = ReturnType<typeof deployUsage>;
1516
export function deployUsage({
1617
environment,
1718
tokens,
19+
postgres,
20+
redis,
1821
kafka,
1922
dbMigrations,
2023
commerce,
@@ -27,6 +30,8 @@ export function deployUsage({
2730
image: string;
2831
environment: Environment;
2932
tokens: Tokens;
33+
postgres: Postgres;
34+
redis: Redis;
3035
kafka: Kafka;
3136
dbMigrations: DbMigrations;
3237
commerce: CommerceService;
@@ -39,60 +44,78 @@ export function deployUsage({
3944
const kafkaBufferDynamic =
4045
kafka.config.bufferDynamic === 'true' || kafka.config.bufferDynamic === '1' ? '1' : '0';
4146

42-
return new ServiceDeployment(
43-
'usage-service',
44-
{
45-
image,
46-
imagePullSecret: docker.secret,
47-
replicas,
48-
readinessProbe: {
49-
initialDelaySeconds: 10,
50-
periodSeconds: 5,
51-
failureThreshold: 2,
52-
timeoutSeconds: 5,
53-
endpoint: '/_readiness',
54-
},
55-
livenessProbe: '/_health',
56-
startupProbe: '/_health',
57-
availabilityOnEveryNode: true,
58-
env: {
59-
...environment.envVars,
60-
SENTRY: sentry.enabled ? '1' : '0',
61-
REQUEST_LOGGING: '0',
62-
KAFKA_BUFFER_SIZE: kafka.config.bufferSize,
63-
KAFKA_SASL_MECHANISM: kafka.config.saslMechanism,
64-
KAFKA_CONCURRENCY: kafka.config.concurrency,
65-
KAFKA_BUFFER_INTERVAL: kafka.config.bufferInterval,
66-
KAFKA_BUFFER_DYNAMIC: kafkaBufferDynamic,
67-
KAFKA_TOPIC: kafka.config.topic,
68-
TOKENS_ENDPOINT: serviceLocalEndpoint(tokens.service),
69-
COMMERCE_ENDPOINT: serviceLocalEndpoint(commerce.service),
70-
OPENTELEMETRY_COLLECTOR_ENDPOINT:
71-
observability.enabled &&
72-
observability.enabledForUsageService &&
73-
observability.tracingEndpoint
74-
? observability.tracingEndpoint
75-
: '',
76-
},
77-
exposesMetrics: true,
78-
port: 4000,
79-
pdb: true,
80-
autoScaling: {
81-
cpu: {
82-
cpuAverageToScale: 60,
83-
limit: cpuLimit,
47+
return (
48+
new ServiceDeployment(
49+
'usage-service',
50+
{
51+
image,
52+
imagePullSecret: docker.secret,
53+
replicas,
54+
readinessProbe: {
55+
initialDelaySeconds: 10,
56+
periodSeconds: 5,
57+
failureThreshold: 2,
58+
timeoutSeconds: 5,
59+
endpoint: '/_readiness',
60+
},
61+
livenessProbe: '/_health',
62+
startupProbe: '/_health',
63+
availabilityOnEveryNode: true,
64+
env: {
65+
...environment.envVars,
66+
SENTRY: sentry.enabled ? '1' : '0',
67+
REQUEST_LOGGING: '0',
68+
KAFKA_BUFFER_SIZE: kafka.config.bufferSize,
69+
KAFKA_SASL_MECHANISM: kafka.config.saslMechanism,
70+
KAFKA_CONCURRENCY: kafka.config.concurrency,
71+
KAFKA_BUFFER_INTERVAL: kafka.config.bufferInterval,
72+
KAFKA_BUFFER_DYNAMIC: kafkaBufferDynamic,
73+
KAFKA_TOPIC: kafka.config.topic,
74+
TOKENS_ENDPOINT: serviceLocalEndpoint(tokens.service),
75+
COMMERCE_ENDPOINT: serviceLocalEndpoint(commerce.service),
76+
OPENTELEMETRY_COLLECTOR_ENDPOINT:
77+
observability.enabled &&
78+
observability.enabledForUsageService &&
79+
observability.tracingEndpoint
80+
? observability.tracingEndpoint
81+
: '',
82+
},
83+
exposesMetrics: true,
84+
port: 4000,
85+
pdb: true,
86+
autoScaling: {
87+
cpu: {
88+
cpuAverageToScale: 60,
89+
limit: cpuLimit,
90+
},
91+
maxReplicas,
8492
},
85-
maxReplicas,
8693
},
87-
},
88-
[dbMigrations, tokens.deployment, tokens.service, commerce.deployment, commerce.service].filter(
89-
Boolean,
90-
),
91-
)
92-
.withSecret('KAFKA_SASL_USERNAME', kafka.secret, 'saslUsername')
93-
.withSecret('KAFKA_SASL_PASSWORD', kafka.secret, 'saslPassword')
94-
.withSecret('KAFKA_SSL', kafka.secret, 'ssl')
95-
.withSecret('KAFKA_BROKER', kafka.secret, 'endpoint')
96-
.withConditionalSecret(sentry.enabled, 'SENTRY_DSN', sentry.secret, 'dsn')
97-
.deploy();
94+
[
95+
dbMigrations,
96+
tokens.deployment,
97+
tokens.service,
98+
commerce.deployment,
99+
commerce.service,
100+
].filter(Boolean),
101+
)
102+
// Redis
103+
.withSecret('REDIS_HOST', redis.secret, 'host')
104+
.withSecret('REDIS_PORT', redis.secret, 'port')
105+
.withSecret('REDIS_PASSWORD', redis.secret, 'password')
106+
// PG
107+
.withSecret('POSTGRES_HOST', postgres.pgBouncerSecret, 'host')
108+
.withSecret('POSTGRES_PORT', postgres.pgBouncerSecret, 'port')
109+
.withSecret('POSTGRES_USER', postgres.pgBouncerSecret, 'user')
110+
.withSecret('POSTGRES_PASSWORD', postgres.pgBouncerSecret, 'password')
111+
.withSecret('POSTGRES_DB', postgres.pgBouncerSecret, 'database')
112+
.withSecret('POSTGRES_SSL', postgres.pgBouncerSecret, 'ssl')
113+
// Kafka
114+
.withSecret('KAFKA_SASL_USERNAME', kafka.secret, 'saslUsername')
115+
.withSecret('KAFKA_SASL_PASSWORD', kafka.secret, 'saslPassword')
116+
.withSecret('KAFKA_SSL', kafka.secret, 'ssl')
117+
.withSecret('KAFKA_BROKER', kafka.secret, 'endpoint')
118+
.withConditionalSecret(sentry.enabled, 'SENTRY_DSN', sentry.secret, 'dsn')
119+
.deploy()
120+
);
98121
}

docker/docker-compose.community.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,14 @@ services:
363363
KAFKA_BUFFER_SIZE: 350
364364
KAFKA_BUFFER_INTERVAL: 1000
365365
KAFKA_BUFFER_DYNAMIC: '1'
366+
POSTGRES_HOST: db
367+
POSTGRES_PORT: 5432
368+
POSTGRES_DB: '${POSTGRES_DB}'
369+
POSTGRES_USER: '${POSTGRES_USER}'
370+
POSTGRES_PASSWORD: '${POSTGRES_PASSWORD}'
371+
REDIS_HOST: redis
372+
REDIS_PORT: 6379
373+
REDIS_PASSWORD: '${REDIS_PASSWORD}'
366374
PORT: 3006
367375
LOG_LEVEL: '${LOG_LEVEL:-debug}'
368376
SENTRY: '${SENTRY:-0}'

integration-tests/testkit/flow.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type {
66
AssignMemberRoleInput,
77
ClientStatsInput,
88
CreateMemberRoleInput,
9+
CreateOrganizationAccessTokenInput,
910
CreateOrganizationInput,
1011
CreateProjectInput,
1112
CreateTargetInput,
@@ -1491,3 +1492,38 @@ export async function updateTargetSchemaComposition(
14911492
token,
14921493
});
14931494
}
1495+
1496+
export function createOrganizationAccessToken(
1497+
input: CreateOrganizationAccessTokenInput,
1498+
authToken: string,
1499+
) {
1500+
return execute({
1501+
document: graphql(`
1502+
mutation CreateOrganizationAccessToken($input: CreateOrganizationAccessTokenInput!) {
1503+
createOrganizationAccessToken(input: $input) {
1504+
ok {
1505+
privateAccessKey
1506+
createdOrganizationAccessToken {
1507+
id
1508+
title
1509+
description
1510+
permissions
1511+
createdAt
1512+
}
1513+
}
1514+
error {
1515+
message
1516+
details {
1517+
title
1518+
description
1519+
}
1520+
}
1521+
}
1522+
}
1523+
`),
1524+
authToken,
1525+
variables: {
1526+
input,
1527+
},
1528+
});
1529+
}

integration-tests/testkit/seed.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
createCdnAccess,
2222
createMemberRole,
2323
createOrganization,
24+
createOrganizationAccessToken,
2425
createProject,
2526
createTarget,
2627
createToken,
@@ -110,6 +111,29 @@ export function initSeed() {
110111

111112
return {
112113
organization,
114+
async createOrganizationAccessToken(args: {
115+
permissions: Array<string>;
116+
resources: GraphQLSchema.ResourceAssignmentInput;
117+
}) {
118+
const result = await createOrganizationAccessToken(
119+
{
120+
title: 'A Access Token',
121+
description: 'access token',
122+
organization: {
123+
byId: organization.id,
124+
},
125+
permissions: args.permissions,
126+
resources: args.resources,
127+
},
128+
ownerToken,
129+
).then(r => r.expectNoGraphQLErrors());
130+
131+
if (result.createOrganizationAccessToken.error) {
132+
throw new Error(result.createOrganizationAccessToken.error.message);
133+
}
134+
135+
return result.createOrganizationAccessToken.ok!.privateAccessKey;
136+
},
113137
async setFeatureFlag(name: string, value: boolean | string[]) {
114138
const pool = await createConnectionPool();
115139

0 commit comments

Comments
 (0)