Skip to content

Commit

Permalink
feat(api7): support consumer credentials (#182)
Browse files Browse the repository at this point in the history
  • Loading branch information
bzp2010 authored Sep 15, 2024
1 parent 8bd118d commit aceb7fe
Show file tree
Hide file tree
Showing 21 changed files with 982 additions and 190 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ jobs:
if: contains(github.event.pull_request.labels.*.name, 'test/api7') || github.event_name == 'push'
strategy:
matrix:
version: [3.2.14.6]
version: [3.2.14.6, 3.2.15.0]
env:
BACKEND_API7_VERSION: ${{ matrix.version }}
BACKEND_API7_DOWNLOAD_URL: https://run.api7.ai/api7-ee/api7-ee-v${{ matrix.version }}.tar.gz
BACKEND_API7_LICENSE: ${{ secrets.BACKEND_API7_LICENSE }}
steps:
Expand Down
84 changes: 72 additions & 12 deletions apps/cli/src/differ/differv3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ const order = {
[`${ADCSDK.ResourceType.PLUGIN_METADATA}.${ADCSDK.EventType.DELETE}`]: 27,
[`${ADCSDK.ResourceType.PLUGIN_METADATA}.${ADCSDK.EventType.CREATE}`]: 28,
[`${ADCSDK.ResourceType.PLUGIN_METADATA}.${ADCSDK.EventType.UPDATE}`]: 29,
[`${ADCSDK.ResourceType.CONSUMER_CREDENTIAL}.${ADCSDK.EventType.DELETE}`]: 30,
[`${ADCSDK.ResourceType.CONSUMER_CREDENTIAL}.${ADCSDK.EventType.CREATE}`]: 31,
[`${ADCSDK.ResourceType.CONSUMER_CREDENTIAL}.${ADCSDK.EventType.UPDATE}`]: 32,
};

export class DifferV3 {
Expand Down Expand Up @@ -163,6 +166,19 @@ export class DifferV3 {
res,
]) ?? [],
),
...differ.diffResource(
ADCSDK.ResourceType.CONSUMER_CREDENTIAL,
local?.consumer_credentials?.map((res) => [
res.name,
ADCSDK.utils.generateId(generateResourceName(res.name)),
res,
]) ?? [],
remote?.consumer_credentials?.map((res) => [
res.name,
ADCSDK.utils.generateId(generateResourceName(res.name)),
res,
]) ?? [],
),
/* ...differ.diffResource(
ADCSDK.ResourceType.UPSTREAM,
local?.upstreams?.map((res) => [
Expand Down Expand Up @@ -262,6 +278,15 @@ export class DifferV3 {
local: Array<[ADCSDK.ResourceName, ADCSDK.ResourceId, ADCSDK.StreamRoute]>,
remote: Array<[ADCSDK.ResourceName, ADCSDK.ResourceId, ADCSDK.StreamRoute]>,
): Array<ADCSDK.Event>;
private diffResource(
resourceType: ADCSDK.ResourceType.CONSUMER_CREDENTIAL,
local: Array<
[ADCSDK.ResourceName, ADCSDK.ResourceId, ADCSDK.ConsumerCredential]
>,
remote: Array<
[ADCSDK.ResourceName, ADCSDK.ResourceId, ADCSDK.ConsumerCredential]
>,
): Array<ADCSDK.Event>;
private diffResource(
resourceType: ADCSDK.ResourceType.UPSTREAM,
local: Array<[ADCSDK.ResourceName, ADCSDK.ResourceId, ADCSDK.Upstream]>,
Expand Down Expand Up @@ -316,6 +341,8 @@ export class DifferV3 {
oldValue: remoteItem,

// Special handling of resources containing nested resources
// When a consumer is deleted, its credentials are not taken into
// consideration.
subEvents: DifferV3.diff(
{},
resourceType === ADCSDK.ResourceType.SERVICE
Expand Down Expand Up @@ -392,33 +419,55 @@ export class DifferV3 {
// Special handling of resources containing nested resources: routes, consumer_groups
const subEvents: Array<ADCSDK.Event> = [];
if (
resourceType === ADCSDK.ResourceType.SERVICE ||
resourceType === ADCSDK.ResourceType.CONSUMER_GROUP
[
ADCSDK.ResourceType.SERVICE,
ADCSDK.ResourceType.CONSUMER_GROUP,
ADCSDK.ResourceType.CONSUMER,
].includes(resourceType)
) {
subEvents.push(
...DifferV3.diff(
resourceType === ADCSDK.ResourceType.SERVICE
resourceType ===
(ADCSDK.ResourceType.SERVICE as ADCSDK.ResourceType)
? {
routes: (localItem as ADCSDK.Service).routes,
stream_routes: (localItem as ADCSDK.Service).stream_routes,
}
: resourceType === ADCSDK.ResourceType.CONSUMER_GROUP
: resourceType ===
(ADCSDK.ResourceType.CONSUMER_GROUP as ADCSDK.ResourceType)
? {
consumers: (localItem as ADCSDK.ConsumerGroup).consumers,
}
: {},
resourceType === ADCSDK.ResourceType.SERVICE
: resourceType ===
(ADCSDK.ResourceType.CONSUMER as ADCSDK.ResourceType)
? {
consumer_credentials: (localItem as ADCSDK.Consumer)
.credentials,
}
: {},
resourceType ===
(ADCSDK.ResourceType.SERVICE as ADCSDK.ResourceType)
? {
routes: (remoteItem as ADCSDK.Service).routes,
stream_routes: (remoteItem as ADCSDK.Service).stream_routes,
}
: resourceType === ADCSDK.ResourceType.CONSUMER_GROUP
: resourceType ===
(ADCSDK.ResourceType.CONSUMER_GROUP as ADCSDK.ResourceType)
? {
consumers: (remoteItem as ADCSDK.ConsumerGroup).consumers,
}
: {},
: resourceType ===
(ADCSDK.ResourceType.CONSUMER as ADCSDK.ResourceType)
? {
consumer_credentials: (remoteItem as ADCSDK.Consumer)
.credentials,
}
: {},
this.defaultValue,
resourceType === ADCSDK.ResourceType.SERVICE
[
ADCSDK.ResourceType.SERVICE,
ADCSDK.ResourceType.CONSUMER,
].includes(resourceType)
? remoteName
: undefined,
).map(this.postprocessSubEvent(remoteName, remoteId)),
Expand All @@ -434,7 +483,9 @@ export class DifferV3 {
// Remove nested resources to indeed compare the main resource itself.
(resourceType === ADCSDK.ResourceType.SERVICE
? ['routes', 'stream_routes']
: ['consumers']
: resourceType === ADCSDK.ResourceType.CONSUMER_GROUP
? ['consumers']
: ['credentials']
).map((key) => {
unset(mergedLocalItem, key);
unset(remoteItem, key);
Expand Down Expand Up @@ -555,10 +606,19 @@ export class DifferV3 {
? {
consumers: (localItem as ADCSDK.ConsumerGroup).consumers,
}
: {},
: resourceType === ADCSDK.ResourceType.CONSUMER
? {
consumer_credentials: (localItem as ADCSDK.Consumer)
.credentials,
}
: {},
{},
this.defaultValue,
resourceType === ADCSDK.ResourceType.SERVICE ? localName : undefined,
[ADCSDK.ResourceType.SERVICE, ADCSDK.ResourceType.CONSUMER].includes(
resourceType,
)
? localName
: undefined,
).map(this.postprocessSubEvent(localName, localId)),
});
});
Expand Down
119 changes: 119 additions & 0 deletions apps/cli/src/differ/specs/consumer.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import * as ADCSDK from '@api7/adc-sdk';

import { DifferV3 } from '../differv3';

describe('Differ V3 - consumer', () => {
it('should create/update/delete consumer credentials', () => {
const consumerName = 'jack';
const changeme = 'changeme';
expect(
DifferV3.diff(
{
consumers: [
{
username: consumerName,
credentials: [
{
name: ADCSDK.EventType.CREATE,
type: 'key-auth',
config: {
key: consumerName,
},
},
{
name: ADCSDK.EventType.UPDATE,
type: 'basic-auth',
config: {
username: consumerName,
password: `${changeme}.new`,
},
},
],
},
],
},
{
consumers: [
{
username: consumerName,
credentials: [
{
name: ADCSDK.EventType.UPDATE,
type: 'basic-auth',
config: {
username: consumerName,
password: changeme,
},
},
{
name: ADCSDK.EventType.DELETE,
type: 'jwt-auth',
config: {
key: consumerName,
secret: changeme,
},
},
],
},
],
},
),
).toEqual([
{
oldValue: {
config: { key: consumerName, secret: changeme },
name: ADCSDK.EventType.DELETE,
type: 'jwt-auth',
},
parentId: consumerName,
resourceId: ADCSDK.utils.generateId(
`${consumerName}.${ADCSDK.EventType.DELETE}`,
),
resourceName: ADCSDK.EventType.DELETE,
resourceType: ADCSDK.ResourceType.CONSUMER_CREDENTIAL,
type: ADCSDK.EventType.DELETE,
},
{
newValue: {
config: { key: consumerName },
name: ADCSDK.EventType.CREATE,
type: 'key-auth',
},
parentId: consumerName,
resourceId: ADCSDK.utils.generateId(
`${consumerName}.${ADCSDK.EventType.CREATE}`,
),
resourceName: ADCSDK.EventType.CREATE,
resourceType: ADCSDK.ResourceType.CONSUMER_CREDENTIAL,
type: ADCSDK.EventType.CREATE,
},
{
diff: [
{
kind: 'E',
lhs: changeme,
path: ['config', 'password'],
rhs: `${changeme}.new`,
},
],
newValue: {
config: { password: `${changeme}.new`, username: consumerName },
name: ADCSDK.EventType.UPDATE,
type: 'basic-auth',
},
oldValue: {
config: { password: changeme, username: consumerName },
name: ADCSDK.EventType.UPDATE,
type: 'basic-auth',
},
parentId: consumerName,
resourceId: ADCSDK.utils.generateId(
`${consumerName}.${ADCSDK.EventType.UPDATE}`,
),
resourceName: ADCSDK.EventType.UPDATE,
resourceType: ADCSDK.ResourceType.CONSUMER_CREDENTIAL,
type: ADCSDK.EventType.UPDATE,
},
]);
});
});
23 changes: 22 additions & 1 deletion apps/cli/src/linter/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ const labelsSchema = z.record(
z.string(),
z.union([z.string(), z.array(z.string())]),
);
const pluginsSchema = z.record(z.string(), z.record(z.string(), z.any()));
const pluginSchema = z.record(z.string(), z.any());
const pluginsSchema = z.record(z.string(), pluginSchema);
const exprSchema = z.array(z.any());
const timeoutSchema = z.object({
connect: z.number().gt(0),
Expand Down Expand Up @@ -289,13 +290,33 @@ const sslSchema = z
})
.strict();

const consumerCredentialSchema = z
.object({
name: nameSchema,
description: descriptionSchema.optional(),
labels: labelsSchema.optional(),

type: z
.string()
.refine(
(type) =>
['key-auth', 'basic-auth', 'jwt-auth', 'hmac-auth'].includes(type),
{
message:
'Consumer credential only supports "key-auth", "basic-auth", "jwt-auth" and "hmac-auth" types',
},
),
config: pluginSchema,
})
.strict();
const consumerSchema = z
.object({
username: nameSchema,
description: descriptionSchema.optional(),
labels: labelsSchema.optional(),

plugins: pluginsSchema.optional(),
credentials: z.array(consumerCredentialSchema).optional(),
})
.strict();

Expand Down
Loading

0 comments on commit aceb7fe

Please sign in to comment.