mirror of
https://github.com/Kong/insomnia.git
synced 2026-10-24 23:59:16 -04:00
Feat/o2k improvements (#3396)
* makes this `yaml` import match all others for better or for worse, until we upgrade `YAML` (it's now written in TypeScript) we should probably aim for consistency. * adds overloads so that types of package exports it would be FAR preferable to use an object with the arguments instead because then we don't have to fall into all the traps that come with overloads, but I am avoiding changing the actual call signature of these function. * fixes and updates types * corrects mispelling * removes shim types and exports actual types from openapi-2-kong we had everything in place for the rest of the build pipeline to consume these types, but were missing the main exports at the root index.ts file * use actual openapi-2-kong types now that they're available * use existing variable for filePath * extracts o2k-specific helper data to live in o2k evidently, this data is useful for the usage of o2k, therefore o2k should be the thing exporting it. * use KubernetesManifest for name of kubernetes manifest union when first naming this, I didn't have much more context than the property name (documents), so after taking a look, it's clear that these are kubernetes manifests * removes attempt at correctly typing overloads I will return to this, and so I'm leaving it here in a commit rather than squashing it out, but I can't see a way to get it to work without changing the signature in a big way. * fixes error (now that there are yaml types) * makes `K8s` vs `Kubernetes` type terminology consistent part of the motivation for this is that there are significant things in common between the two kinds of configs, making them closer in form is therefore ideal. * updates mistake in name per review feedback
This commit is contained in:
1 parent
fa72e0977b
commit
3605bc17cc
19 files changed
+142
-169
No files matched your search
@@ -97,5 +97,7 @@ module.exports = {
|
||||
'@typescript-eslint/quotes': ['error', 'single', { avoidEscape: true }],
|
||||
'no-use-before-define': 'off',
|
||||
'@typescript-eslint/no-use-before-define': 'error',
|
||||
'no-redeclare': 'off',
|
||||
'@typescript-eslint/no-redeclare': 'error',
|
||||
},
|
||||
};
|
||||
@@ -91,7 +91,7 @@ Generate configuration from an api spec.
|
||||
|
||||
Options:
|
||||
-t, --type <value> type of configuration to generate, options are
|
||||
[kubernetes, declarative] (default: declarative)
|
||||
[declarative, kubernetes] (default: declarative)
|
||||
--tags <tags> comma separated list of tags to apply to each entity
|
||||
-o, --output <path> save the generated config to a file
|
||||
-h, --help display help for command"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { conversionTypeMap, generateConfig } from './commands/generate-config';
|
||||
import { ConversionOption, conversionOptions, generateConfig } from './commands/generate-config';
|
||||
import { getVersion, logErrorExit1, exit } from './util';
|
||||
import { reporterTypes, runInsomniaTests, TestReporter } from './commands/run-tests';
|
||||
import { lintSpecification } from './commands/lint-specification';
|
||||
@@ -24,7 +24,7 @@ type CreateCommand = (command: string) => commander.Command
|
||||
const makeGenerateCommand = (commandCreator: CreateCommand) => {
|
||||
// inso generate
|
||||
const command = commandCreator('generate').description('Code generation utilities');
|
||||
const defaultType: keyof typeof conversionTypeMap = 'declarative';
|
||||
const defaultType: ConversionOption = 'declarative';
|
||||
|
||||
// inso generate config -t kubernetes config.yaml
|
||||
command
|
||||
@@ -32,7 +32,7 @@ const makeGenerateCommand = (commandCreator: CreateCommand) => {
|
||||
.description('Generate configuration from an api spec.')
|
||||
.option(
|
||||
'-t, --type <value>',
|
||||
`type of configuration to generate, options are [${Object.keys(conversionTypeMap).join(', ')}] (default: ${defaultType})`,
|
||||
`type of configuration to generate, options are [${conversionOptions.join(', ')}] (default: ${defaultType})`,
|
||||
)
|
||||
.option('--tags <tags>', 'comma separated list of tags to apply to each entity')
|
||||
.option('-o, --output <path>', 'save the generated config to a file')
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { conversionTypeMap, generateConfig, GenerateConfigOptions } from './generate-config';
|
||||
import { ConversionResult, generate as _generate, generateFromString as _generateFromString } from 'openapi-2-kong';
|
||||
import { generate as _generate, generateFromString as _generateFromString, KongForKubernetesResult } from 'openapi-2-kong';
|
||||
import path from 'path';
|
||||
import { writeFileWithCliOptions as _writeFileWithCliOptions } from '../write-file';
|
||||
import { globalBeforeAll, globalBeforeEach } from '../jest/before';
|
||||
@@ -14,7 +14,8 @@ const generate = _generate as jest.MockedFunction<typeof _generate>;
|
||||
const generateFromString = _generateFromString as jest.MockedFunction<typeof _generateFromString>;
|
||||
const writeFileWithCliOptions = _writeFileWithCliOptions as jest.MockedFunction<typeof _writeFileWithCliOptions>;
|
||||
|
||||
const mockConversionResult: ConversionResult = {
|
||||
const mockConversionResult: KongForKubernetesResult = {
|
||||
// @ts-expect-error -- TSCONVERSION the tests seem to suggest that this is valid, yet it is not allowed by the types.
|
||||
documents: ['a', 'b'],
|
||||
type: 'kong-for-kubernetes',
|
||||
label: '',
|
||||
@@ -43,7 +44,7 @@ describe('generateConfig()', () => {
|
||||
});
|
||||
expect(generate).not.toHaveBeenCalled();
|
||||
expect(logger.__getLogs().fatal).toEqual([
|
||||
'Config type "invalid" not unrecognized. Options are [kubernetes, declarative].',
|
||||
'Config type "invalid" not unrecognized. Options are [declarative, kubernetes].',
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -108,7 +109,7 @@ describe('generateConfig()', () => {
|
||||
generate.mockResolvedValue(mockConversionResult);
|
||||
const outputPath = 'this-is-the-output-path';
|
||||
writeFileWithCliOptions.mockResolvedValue(outputPath);
|
||||
const result = await generateConfig('file.yaml', {
|
||||
const result = await generateConfig(filePath, {
|
||||
type: 'kubernetes',
|
||||
workingDir: 'test/dir',
|
||||
output: 'output.yaml',
|
||||
@@ -127,7 +128,7 @@ describe('generateConfig()', () => {
|
||||
generate.mockResolvedValue(mockConversionResult);
|
||||
const outputPath = 'this-is-the-output-path';
|
||||
writeFileWithCliOptions.mockResolvedValue(outputPath);
|
||||
const absolutePath = path.join(os.tmpdir(), 'dev', 'file.yaml');
|
||||
const absolutePath = path.join(os.tmpdir(), 'dev', filePath);
|
||||
const result = await generateConfig(absolutePath, {
|
||||
type: 'kubernetes',
|
||||
workingDir: 'test/dir',
|
||||
@@ -143,7 +144,7 @@ describe('generateConfig()', () => {
|
||||
it('should throw InsoError if there is an error thrown by openapi-2-kong', async () => {
|
||||
const error = new Error('err');
|
||||
generate.mockRejectedValue(error);
|
||||
const promise = generateConfig('file.yaml', { type: 'kubernetes' });
|
||||
const promise = generateConfig(filePath, { type: 'kubernetes' });
|
||||
await expect(promise).rejects.toThrowError(
|
||||
new InsoError('There was an error while generating configuration', error),
|
||||
);
|
||||
@@ -152,7 +153,7 @@ describe('generateConfig()', () => {
|
||||
it('should warn if no valid spec can be found', async () => {
|
||||
// @ts-expect-error intentionally passing in a bad value
|
||||
generate.mockResolvedValue({});
|
||||
const result = await generateConfig('file.yaml', { type: 'kubernetes' });
|
||||
const result = await generateConfig(filePath, { type: 'kubernetes' });
|
||||
expect(result).toBe(false);
|
||||
expect(logger.__getLogs().log).toEqual([
|
||||
'Could not find a valid specification to generate configuration.',
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ConversionResult, ConversionResultType, generate, generateFromString } from 'openapi-2-kong';
|
||||
import { ConversionResult, ConversionResultType, DeclarativeConfig, generate, generateFromString, K8sManifest } from 'openapi-2-kong';
|
||||
import YAML from 'yaml';
|
||||
import path from 'path';
|
||||
import type { GlobalOptions } from '../get-options';
|
||||
@@ -8,18 +8,20 @@ import { writeFileWithCliOptions } from '../write-file';
|
||||
import { logger } from '../logger';
|
||||
import { InsoError } from '../errors';
|
||||
|
||||
export const conversionTypeMap = {
|
||||
export type ConversionOption = 'kubernetes' | 'declarative';
|
||||
|
||||
export const conversionOptions: ConversionOption[] = [
|
||||
'declarative',
|
||||
'kubernetes',
|
||||
];
|
||||
|
||||
export const conversionTypeMap: Record<ConversionOption, ConversionResultType> = {
|
||||
kubernetes: 'kong-for-kubernetes',
|
||||
declarative: 'kong-declarative-config',
|
||||
} as const;
|
||||
|
||||
export const conversionTypes: ConversionResultType[] = [
|
||||
'kong-declarative-config',
|
||||
'kong-for-kubernetes',
|
||||
];
|
||||
|
||||
export type GenerateConfigOptions = GlobalOptions & {
|
||||
type: keyof (typeof conversionTypeMap);
|
||||
type: ConversionOption;
|
||||
output?: string;
|
||||
tags?: string,
|
||||
};
|
||||
@@ -29,7 +31,7 @@ const validateOptions = (
|
||||
): options is Partial<GenerateConfigOptions> & Pick<GenerateConfigOptions, 'type'> => {
|
||||
const { type } = options;
|
||||
if (!type || !conversionTypeMap[type]) {
|
||||
logger.fatal(`Config type "${type}" not unrecognized. Options are [${Object.keys(conversionTypeMap).join(', ')}].`);
|
||||
logger.fatal(`Config type "${type}" not unrecognized. Options are [${conversionOptions.join(', ')}].`);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -57,13 +59,13 @@ export const generateConfig = async (
|
||||
const specFromDb = identifier ? loadApiSpec(db, identifier) : await promptApiSpec(db, !!ci);
|
||||
|
||||
const generationTags = tags?.split(',');
|
||||
|
||||
const conversionType = conversionTypeMap[type];
|
||||
try {
|
||||
if (specFromDb?.contents) {
|
||||
logger.trace('Generating config from database contents');
|
||||
result = await generateFromString(
|
||||
specFromDb.contents,
|
||||
conversionTypeMap[type],
|
||||
conversionType,
|
||||
generationTags,
|
||||
);
|
||||
} else if (identifier) {
|
||||
@@ -72,7 +74,7 @@ export const generateConfig = async (
|
||||
? identifier
|
||||
: path.join(workingDir || '.', identifier);
|
||||
logger.trace(`Generating config from file \`${fileName}\``);
|
||||
result = await generate(fileName, conversionTypeMap[type], generationTags);
|
||||
result = await generate(fileName, conversionType, generationTags);
|
||||
}
|
||||
} catch (e) {
|
||||
throw new InsoError('There was an error while generating configuration', e);
|
||||
@@ -83,7 +85,7 @@ export const generateConfig = async (
|
||||
return false;
|
||||
}
|
||||
|
||||
const yamlDocs = result.documents.map(document => YAML.stringify(document));
|
||||
const yamlDocs = result.documents.map((document: DeclarativeConfig | K8sManifest) => YAML.stringify(document));
|
||||
// Join the YAML docs with "---" and strip any extra newlines surrounding them
|
||||
const document = yamlDocs.join('\n---\n').replace(/\n+---\n+/g, '\n---\n');
|
||||
|
||||
|
||||
-57
@@ -1,57 +0,0 @@
|
||||
// TODO(TSCONVERSION) remove this when the conversion for o2k is complete
|
||||
|
||||
declare module 'openapi-2-kong' {
|
||||
/** TODO(TSCONVERSION) this can be taken from the official types OpenAPIV3.Document */
|
||||
interface OpenAPI3Document {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
[todo: string]: any;
|
||||
}
|
||||
|
||||
export type ConversionResultType = 'kong-declarative-config' | 'kong-for-kubernetes'
|
||||
|
||||
export interface DeclarativeConfigResult {
|
||||
type: 'kong-declarative-config',
|
||||
label: string,
|
||||
documents: Object,
|
||||
warnings: {
|
||||
severity: number,
|
||||
message: string,
|
||||
range: {
|
||||
/* TODO */
|
||||
},
|
||||
}[],
|
||||
}
|
||||
|
||||
export interface KongForKubernetesResult {
|
||||
type: 'kong-for-kubernetes',
|
||||
label: string,
|
||||
documents: Object[],
|
||||
warnings: {
|
||||
severity: number,
|
||||
message: string,
|
||||
range: {
|
||||
/* TODO */
|
||||
},
|
||||
}[],
|
||||
}
|
||||
|
||||
export type ConversionResult = DeclarativeConfigResult | KongForKubernetesResult;
|
||||
|
||||
export function generateFromString(
|
||||
spec: string,
|
||||
type: ConversionResultType,
|
||||
tags?: string[],
|
||||
): Promise<ConversionResult>
|
||||
|
||||
export function generateFromSpec(
|
||||
spec: OpenAPI3Document,
|
||||
type: ConversionResultType,
|
||||
tags?: string[]
|
||||
): Promise<ConversionResult>
|
||||
|
||||
export function generate(
|
||||
filename: string,
|
||||
type: ConversionResultType,
|
||||
tags?: string[],
|
||||
): Promise<ConversionResult>
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
import { DeclarativeConfig } from '../types/declarative-config';
|
||||
import { OpenApi3Spec } from '../types/openapi3';
|
||||
import { DeclarativeConfigResult } from '../types/outputs';
|
||||
import { generateServices } from './services';
|
||||
@@ -6,28 +7,26 @@ import { generateUpstreams } from './upstreams';
|
||||
export function generateDeclarativeConfigFromSpec(
|
||||
api: OpenApi3Spec,
|
||||
tags: string[],
|
||||
): DeclarativeConfigResult {
|
||||
let document = null;
|
||||
|
||||
) {
|
||||
try {
|
||||
document = {
|
||||
const document: DeclarativeConfig = {
|
||||
_format_version: '1.1',
|
||||
services: generateServices(api, tags),
|
||||
upstreams: generateUpstreams(api, tags),
|
||||
};
|
||||
} catch (err) {
|
||||
throw new Error('Failed to generate spec: ' + err.message);
|
||||
}
|
||||
|
||||
// This remover any circular references or weirdness that might result
|
||||
// from the JS objects used.
|
||||
// SEE: https://github.com/Kong/studio/issues/93
|
||||
return JSON.parse(
|
||||
JSON.stringify({
|
||||
const declarativeConfigResult: DeclarativeConfigResult = {
|
||||
type: 'kong-declarative-config',
|
||||
label: 'Kong Declarative Config',
|
||||
documents: [document],
|
||||
warnings: [],
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
// This remover any circular references or weirdness that might result
|
||||
// from the JS objects used.
|
||||
// SEE: https://github.com/Kong/studio/issues/93
|
||||
const result: DeclarativeConfigResult = JSON.parse(JSON.stringify(declarativeConfigResult));
|
||||
return result;
|
||||
} catch (err) {
|
||||
throw new Error('Failed to generate spec: ' + err.message);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import { getSpec } from './utils';
|
||||
|
||||
const xKongUpstreamDefaults = 'x-kong-upstream-defaults';
|
||||
|
||||
/** This function is written in such a way as to allow mutations in tests but without affecting other tests. */
|
||||
const getSpecResult = () =>
|
||||
JSON.parse(
|
||||
JSON.stringify({
|
||||
|
||||
@@ -15,11 +15,10 @@ describe('fixtures', () => {
|
||||
|
||||
it(`converts ${fileBase}`, async () => {
|
||||
const result = await generate(inputPath, 'kong-declarative-config');
|
||||
// @ts-expect-error -- TSCONVERSION
|
||||
expect(result.documents.length).toBe(1);
|
||||
const document = result.documents[0];
|
||||
|
||||
const expectedObj = JSON.parse(expected) as DeclarativeConfig;
|
||||
const expectedObj: DeclarativeConfig = JSON.parse(expected);
|
||||
|
||||
// Make matching friendlier
|
||||
for (const service of expectedObj.services || []) {
|
||||
|
||||
@@ -8,7 +8,6 @@ describe('index', () => {
|
||||
it('generates DC from file', async () => {
|
||||
const p = path.join(__dirname, './fixtures/uspto.yaml');
|
||||
const {
|
||||
// @ts-expect-error -- TSCONVERSION
|
||||
documents: [dc],
|
||||
} = await generate(p, 'kong-declarative-config');
|
||||
expect(dc._format_version).toBe('1.1');
|
||||
|
||||
@@ -5,10 +5,15 @@ import { generateKongForKubernetesConfigFromSpec } from './kubernetes';
|
||||
import SwaggerParser from 'swagger-parser';
|
||||
import { OpenApi3Spec } from './types/openapi3';
|
||||
import { ConversionResultType, ConversionResult } from './types/outputs';
|
||||
import { parse as YAMLparse } from 'yaml';
|
||||
import YAML from 'yaml';
|
||||
|
||||
const defaultTags = ['OAS3_import'];
|
||||
|
||||
export const conversionTypes: ConversionResultType[] = [
|
||||
'kong-declarative-config',
|
||||
'kong-for-kubernetes',
|
||||
];
|
||||
|
||||
export async function generate(
|
||||
specPath: string,
|
||||
type: ConversionResultType,
|
||||
@@ -63,7 +68,7 @@ export async function parseSpec(spec: string | Record<string, any>) {
|
||||
try {
|
||||
api = JSON.parse(spec);
|
||||
} catch (err) {
|
||||
api = YAMLparse(spec);
|
||||
api = YAML.parse(spec);
|
||||
}
|
||||
} else {
|
||||
api = JSON.parse(JSON.stringify(spec));
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
export {
|
||||
conversionTypes,
|
||||
generate,
|
||||
generateFromString,
|
||||
generateFromSpec,
|
||||
parseSpec,
|
||||
} from './generate';
|
||||
|
||||
export * from './types/declarative-config';
|
||||
export * from './types/k8splugins';
|
||||
export * from './types/kubernetes-config';
|
||||
export * from './types/openapi3';
|
||||
export * from './types/outputs';
|
||||
@@ -2,8 +2,8 @@ import { getMethodAnnotationName, getName, HttpMethodType, parseUrl } from '../c
|
||||
import urlJoin from 'url-join';
|
||||
import { flattenPluginDocuments, getPlugins, prioritizePlugins } from './plugins';
|
||||
import { pathVariablesToWildcard, resolveUrlVariables } from './variables';
|
||||
import { IndexIncrement } from '../types/k8plugins';
|
||||
import { KubernetesConfig, KubernetesMethodConfig, K8sMetadata, K8sAnnotations, K8sIngressRule, K8sPath } from '../types/kubernetes-config';
|
||||
import { IndexIncrement } from '../types/k8splugins';
|
||||
import { K8sConfig, K8sMethodConfig, K8sMetadata, K8sAnnotations, K8sIngressRule, K8sPath } from '../types/kubernetes-config';
|
||||
import { OpenApi3Spec, OA3Server } from '../types/openapi3';
|
||||
import { KongForKubernetesResult } from '../types/outputs';
|
||||
|
||||
@@ -12,15 +12,15 @@ interface CustomAnnotations {
|
||||
overrideName?: string;
|
||||
}
|
||||
|
||||
export function generateKongForKubernetesConfigFromSpec(api: OpenApi3Spec): KongForKubernetesResult {
|
||||
export function generateKongForKubernetesConfigFromSpec(api: OpenApi3Spec) {
|
||||
const specName = getSpecName(api);
|
||||
|
||||
// Extract global, server, and path plugins upfront
|
||||
const plugins = getPlugins(api);
|
||||
|
||||
// Initialize document collections
|
||||
const ingressDocuments = [];
|
||||
const methodsThatNeedKongIngressDocuments: Set<HttpMethodType> = new Set<HttpMethodType>();
|
||||
const ingressDocuments: K8sConfig[] = [];
|
||||
const methodsThatNeedKongIngressDocuments = new Set<HttpMethodType>();
|
||||
let _iterator = 0;
|
||||
|
||||
const increment = (): number => _iterator++;
|
||||
@@ -47,7 +47,7 @@ export function generateKongForKubernetesConfigFromSpec(api: OpenApi3Spec): Kong
|
||||
// Create metadata
|
||||
const metadata = generateMetadata(api, annotations, increment, specName);
|
||||
// Generate Kong ingress document for a server and path in the doc
|
||||
const doc: KubernetesConfig = {
|
||||
const doc: K8sConfig = {
|
||||
apiVersion: 'extensions/v1beta1',
|
||||
kind: 'Ingress',
|
||||
metadata,
|
||||
@@ -68,15 +68,16 @@ export function generateKongForKubernetesConfigFromSpec(api: OpenApi3Spec): Kong
|
||||
|
||||
const documents = [...methodDocuments, ...pluginDocuments, ...ingressDocuments];
|
||||
|
||||
return {
|
||||
const result: KongForKubernetesResult = {
|
||||
type: 'kong-for-kubernetes',
|
||||
label: 'Kong for Kubernetes',
|
||||
documents,
|
||||
warnings: [],
|
||||
} as KongForKubernetesResult;
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
function generateK8sMethodDocuments(method: HttpMethodType): KubernetesMethodConfig {
|
||||
function generateK8sMethodDocuments(method: HttpMethodType): K8sMethodConfig {
|
||||
return {
|
||||
apiVersion: 'configuration.konghq.com/v1',
|
||||
kind: 'KongIngress',
|
||||
@@ -116,7 +117,7 @@ export function getSpecName(api: OpenApi3Spec): string {
|
||||
export function generateMetadataAnnotations(
|
||||
api: OpenApi3Spec,
|
||||
{ pluginNames, overrideName }: CustomAnnotations,
|
||||
): K8sAnnotations {
|
||||
) {
|
||||
// This annotation is required by kong-ingress-controller
|
||||
// https://github.com/Kong/kubernetes-ingress-controller/blob/main/docs/references/annotations.md#kubernetesioingressclass
|
||||
const coreAnnotations: K8sAnnotations = {
|
||||
@@ -126,7 +127,7 @@ export function generateMetadataAnnotations(
|
||||
|
||||
// Only continue if metadata annotations, or plugins, or overrides exist
|
||||
if (metadata?.annotations || pluginNames.length || overrideName) {
|
||||
const customAnnotations = {};
|
||||
const customAnnotations: K8sAnnotations = {};
|
||||
|
||||
if (pluginNames.length) {
|
||||
customAnnotations['konghq.com/plugins'] = pluginNames.join(', ');
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { KubernetesPluginConfig } from '../types/kubernetes-config';
|
||||
import { K8sPluginConfig } from '../types/kubernetes-config';
|
||||
import { XKongPluginKeyAuth, XKongPluginUnknown } from '../types/openapi3';
|
||||
|
||||
export const pluginKeyAuth: XKongPluginKeyAuth = {
|
||||
@@ -21,7 +21,7 @@ export const pluginDummy: XKongPluginUnknown<{ foo: 'bar' }> = {
|
||||
},
|
||||
};
|
||||
|
||||
export const pluginDocWithName = (name: string, pluginType: string): KubernetesPluginConfig => ({
|
||||
export const pluginDocWithName = (name: string, pluginType: string): K8sPluginConfig => ({
|
||||
apiVersion: 'configuration.konghq.com/v1',
|
||||
kind: 'KongPlugin',
|
||||
metadata: {
|
||||
@@ -44,7 +44,7 @@ export const keyAuthPluginDoc = (suffix: string) => ({
|
||||
plugin: 'key-auth',
|
||||
});
|
||||
|
||||
export const dummyPluginDoc = (suffix: string): KubernetesPluginConfig => ({
|
||||
export const dummyPluginDoc = (suffix: string): K8sPluginConfig => ({
|
||||
apiVersion: 'configuration.konghq.com/v1',
|
||||
config: {
|
||||
foo: 'bar',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {
|
||||
flattenPluginDocuments,
|
||||
generateK8PluginConfig,
|
||||
generateK8sPluginConfig,
|
||||
getGlobalPlugins,
|
||||
getOperationPlugins,
|
||||
getPathPlugins,
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
pluginDummy,
|
||||
pluginKeyAuth,
|
||||
} from './plugin-helpers';
|
||||
import { PathPlugin, OperationPlugin } from '../types/k8plugins';
|
||||
import { PathPlugin, OperationPlugin } from '../types/k8splugins';
|
||||
import { OpenApi3Spec, OA3Server, OA3Paths, OA3PathItem, OA3Components } from '../types/openapi3';
|
||||
|
||||
describe('plugins', () => {
|
||||
@@ -424,10 +424,10 @@ describe('plugins', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('generateK8PluginConfig()', () => {
|
||||
describe('generateK8sPluginConfig()', () => {
|
||||
it('should return empty array if no plugin keys found and not increment', () => {
|
||||
const incrementMock = jest.fn().mockReturnValue(0);
|
||||
const result = generateK8PluginConfig(spec, 's', incrementMock);
|
||||
const result = generateK8sPluginConfig(spec, 's', incrementMock);
|
||||
expect(result).toHaveLength(0);
|
||||
expect(incrementMock).not.toHaveBeenCalled();
|
||||
});
|
||||
@@ -435,7 +435,7 @@ describe('plugins', () => {
|
||||
it('should attach config onto plugin if it exists and increment', () => {
|
||||
const incrementMock = jest.fn().mockReturnValue(0);
|
||||
// @ts-expect-error -- TSCONVERSION not sure, but this is intentionally different maybe?
|
||||
const result = generateK8PluginConfig({ ...spec, ...pluginKeyAuth }, 'greg', incrementMock);
|
||||
const result = generateK8sPluginConfig({ ...spec, ...pluginKeyAuth }, 'greg', incrementMock);
|
||||
expect(result).toEqual([keyAuthPluginDoc('greg0')]);
|
||||
expect(incrementMock).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
@@ -8,13 +8,13 @@ import {
|
||||
} from '../common';
|
||||
import { generateSecurityPlugins } from '../declarative-config/security-plugins';
|
||||
import { DCPlugin } from '../types/declarative-config';
|
||||
import { Plugins, IndexIncrement, ServerPlugin, PathPlugin, OperationPlugin } from '../types/k8plugins';
|
||||
import { KubernetesPluginConfig } from '../types/kubernetes-config';
|
||||
import { Plugins, IndexIncrement, ServerPlugin, PathPlugin, OperationPlugin } from '../types/k8splugins';
|
||||
import { K8sPluginConfig } from '../types/kubernetes-config';
|
||||
import { OpenApi3Spec, OA3Server, OA3Paths, OA3PathItem } from '../types/openapi3';
|
||||
import { ValueOf } from 'type-fest';
|
||||
|
||||
export function flattenPluginDocuments(plugins: Plugins): KubernetesPluginConfig[] {
|
||||
const all: KubernetesPluginConfig[] = [];
|
||||
export function flattenPluginDocuments(plugins: Plugins): K8sPluginConfig[] {
|
||||
const all: K8sPluginConfig[] = [];
|
||||
const { global, servers, paths } = plugins;
|
||||
all.push(...global);
|
||||
servers.forEach(s => {
|
||||
@@ -52,13 +52,13 @@ export function getPlugins(api: OpenApi3Spec): Plugins {
|
||||
// NOTE: It isn't great that we're relying on declarative-config stuff here but there's
|
||||
// not much we can do about it. If we end up needing this again, it should be factored
|
||||
// out to a higher-level.
|
||||
export function mapDcPluginsToK8Plugins(
|
||||
export function mapDcPluginsToK8sPlugins(
|
||||
dcPlugins: DCPlugin[],
|
||||
suffix: string,
|
||||
increment: IndexIncrement,
|
||||
) {
|
||||
return dcPlugins.map(dcPlugin => {
|
||||
const k8sPlugin: KubernetesPluginConfig = {
|
||||
const k8sPlugin: K8sPluginConfig = {
|
||||
apiVersion: 'configuration.konghq.com/v1',
|
||||
kind: 'KongPlugin',
|
||||
metadata: {
|
||||
@@ -77,13 +77,13 @@ export function mapDcPluginsToK8Plugins(
|
||||
|
||||
export function getGlobalPlugins(api: OpenApi3Spec, increment: IndexIncrement) {
|
||||
const pluginNameSuffix = PluginNameSuffix.global;
|
||||
const globalK8Plugins = generateK8PluginConfig(api, pluginNameSuffix, increment);
|
||||
const securityPlugins = mapDcPluginsToK8Plugins(
|
||||
const globalK8sPlugins = generateK8sPluginConfig(api, pluginNameSuffix, increment);
|
||||
const securityPlugins = mapDcPluginsToK8sPlugins(
|
||||
generateSecurityPlugins(null, api, []),
|
||||
pluginNameSuffix,
|
||||
increment,
|
||||
);
|
||||
return [...globalK8Plugins, ...securityPlugins];
|
||||
return [...globalK8sPlugins, ...securityPlugins];
|
||||
}
|
||||
|
||||
export function getServerPlugins(
|
||||
@@ -92,7 +92,7 @@ export function getServerPlugins(
|
||||
) {
|
||||
return servers.map<ServerPlugin>(server => ({
|
||||
server,
|
||||
plugins: generateK8PluginConfig(server, PluginNameSuffix.server, increment),
|
||||
plugins: generateK8sPluginConfig(server, PluginNameSuffix.server, increment),
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ export function getPathPlugins(paths: OA3Paths, increment: IndexIncrement, api:
|
||||
const pathItem = paths[path];
|
||||
return {
|
||||
path,
|
||||
plugins: generateK8PluginConfig(pathItem, PluginNameSuffix.path, increment),
|
||||
plugins: generateK8sPluginConfig(pathItem, PluginNameSuffix.path, increment),
|
||||
operations: normalizeOperationPlugins(getOperationPlugins(pathItem, increment, api)),
|
||||
};
|
||||
});
|
||||
@@ -119,8 +119,8 @@ export function getOperationPlugins(
|
||||
// We know this will always, only be OA3Operation (because of the filter above), but Flow doesn't know that...
|
||||
const operation: Record<string, any> = pathItem[key];
|
||||
const pluginNameSuffix = PluginNameSuffix.operation;
|
||||
const opPlugins = generateK8PluginConfig(operation, pluginNameSuffix, increment);
|
||||
const securityPlugins = mapDcPluginsToK8Plugins(
|
||||
const opPlugins = generateK8sPluginConfig(operation, pluginNameSuffix, increment);
|
||||
const securityPlugins = mapDcPluginsToK8sPlugins(
|
||||
generateSecurityPlugins(operation, api, []),
|
||||
pluginNameSuffix,
|
||||
increment,
|
||||
@@ -144,17 +144,17 @@ const PluginNameSuffix = {
|
||||
|
||||
type PluginNameSuffixKeys = ValueOf<typeof PluginNameSuffix>;
|
||||
|
||||
export function generateK8PluginConfig(
|
||||
export function generateK8sPluginConfig(
|
||||
obj: Record<string, any>,
|
||||
pluginNameSuffix: PluginNameSuffixKeys,
|
||||
increment: IndexIncrement,
|
||||
) {
|
||||
const plugins: KubernetesPluginConfig[] = [];
|
||||
const plugins: K8sPluginConfig[] = [];
|
||||
|
||||
for (const key of Object.keys(obj).filter(isPluginKey)) {
|
||||
const pData = obj[key];
|
||||
const name = pData.name || getPluginNameFromKey(key);
|
||||
const p: KubernetesPluginConfig = {
|
||||
const p: K8sPluginConfig = {
|
||||
apiVersion: 'configuration.konghq.com/v1',
|
||||
kind: 'KongPlugin',
|
||||
metadata: {
|
||||
@@ -197,13 +197,13 @@ export function normalizeOperationPlugins(operationPlugins: OperationPlugin[]) {
|
||||
}
|
||||
|
||||
export function prioritizePlugins(
|
||||
global: KubernetesPluginConfig[],
|
||||
server: KubernetesPluginConfig[],
|
||||
path: KubernetesPluginConfig[],
|
||||
operation: KubernetesPluginConfig[],
|
||||
global: K8sPluginConfig[],
|
||||
server: K8sPluginConfig[],
|
||||
path: K8sPluginConfig[],
|
||||
operation: K8sPluginConfig[],
|
||||
) {
|
||||
// Order in priority: operation > path > server > global
|
||||
const plugins: KubernetesPluginConfig[] = [...operation, ...path, ...server, ...global];
|
||||
const plugins: K8sPluginConfig[] = [...operation, ...path, ...server, ...global];
|
||||
// Select first of each type of plugin
|
||||
return distinctByProperty(plugins, p => p.plugin);
|
||||
}
|
||||
+5
-5
@@ -1,25 +1,25 @@
|
||||
import { HttpMethodType } from '../common';
|
||||
import { KubernetesPluginConfig } from './kubernetes-config';
|
||||
import { K8sPluginConfig } from './kubernetes-config';
|
||||
import { OA3Server } from './openapi3';
|
||||
|
||||
export interface OperationPlugin {
|
||||
method?: HttpMethodType | null;
|
||||
plugins: KubernetesPluginConfig[];
|
||||
plugins: K8sPluginConfig[];
|
||||
}
|
||||
|
||||
export interface PathPlugin {
|
||||
path: string;
|
||||
plugins: KubernetesPluginConfig[];
|
||||
plugins: K8sPluginConfig[];
|
||||
operations: OperationPlugin[];
|
||||
}
|
||||
|
||||
export interface ServerPlugin {
|
||||
server: OA3Server;
|
||||
plugins: KubernetesPluginConfig[];
|
||||
plugins: K8sPluginConfig[];
|
||||
}
|
||||
|
||||
export interface Plugins {
|
||||
global: KubernetesPluginConfig[];
|
||||
global: K8sPluginConfig[];
|
||||
servers: ServerPlugin[];
|
||||
paths: PathPlugin[];
|
||||
}
|
||||
@@ -1,10 +1,24 @@
|
||||
import { HttpMethodType } from '../common';
|
||||
|
||||
export interface K8sAnnotations {
|
||||
'kubernetes.io/ingress.class': 'kong';
|
||||
[key: string]: string;
|
||||
export interface K8sIngressClassAnnotation {
|
||||
'kubernetes.io/ingress.class'?: 'kong';
|
||||
}
|
||||
|
||||
export interface K8sPluginsAnnotation {
|
||||
'konghq.com/plugins'?: string;
|
||||
}
|
||||
|
||||
export interface K8sOverrideAnnotation {
|
||||
'konghq.com/override'?: string;
|
||||
}
|
||||
|
||||
export type K8sAnnotations =
|
||||
& K8sIngressClassAnnotation
|
||||
& K8sOverrideAnnotation
|
||||
& K8sPluginsAnnotation
|
||||
& Record<string, string>
|
||||
;
|
||||
|
||||
export interface K8sMetadata {
|
||||
name: string;
|
||||
annotations: K8sAnnotations;
|
||||
@@ -37,7 +51,7 @@ export interface K8sSpec {
|
||||
rules: K8sIngressRule[];
|
||||
}
|
||||
|
||||
export interface KubernetesMethodConfig {
|
||||
export interface K8sMethodConfig {
|
||||
apiVersion: 'configuration.konghq.com/v1';
|
||||
kind: 'KongIngress';
|
||||
metadata: {
|
||||
@@ -48,7 +62,7 @@ export interface KubernetesMethodConfig {
|
||||
};
|
||||
}
|
||||
|
||||
export interface KubernetesPluginConfig {
|
||||
export interface K8sPluginConfig {
|
||||
apiVersion: 'configuration.konghq.com/v1';
|
||||
kind: 'KongPlugin';
|
||||
metadata: {
|
||||
@@ -59,9 +73,15 @@ export interface KubernetesPluginConfig {
|
||||
plugin: string;
|
||||
}
|
||||
|
||||
export interface KubernetesConfig {
|
||||
export interface K8sConfig {
|
||||
apiVersion: 'extensions/v1beta1';
|
||||
kind: 'Ingress';
|
||||
metadata: K8sMetadata;
|
||||
spec: K8sSpec;
|
||||
}
|
||||
|
||||
export type K8sManifest =
|
||||
| K8sConfig
|
||||
| K8sMethodConfig
|
||||
| K8sPluginConfig
|
||||
;
|
||||
@@ -1,32 +1,26 @@
|
||||
import { DeclarativeConfig } from './declarative-config';
|
||||
import {
|
||||
KubernetesConfig,
|
||||
KubernetesMethodConfig,
|
||||
KubernetesPluginConfig,
|
||||
} from './kubernetes-config';
|
||||
import { K8sManifest } from './kubernetes-config';
|
||||
|
||||
export type ConversionResultType = 'kong-declarative-config' | 'kong-for-kubernetes';
|
||||
|
||||
export interface Warning {
|
||||
severity: number;
|
||||
message: string;
|
||||
range: {};
|
||||
}
|
||||
|
||||
export interface DeclarativeConfigResult {
|
||||
type: 'kong-declarative-config';
|
||||
label: string;
|
||||
documents: DeclarativeConfig;
|
||||
warnings: {
|
||||
severity: number;
|
||||
message: string;
|
||||
range: {};
|
||||
}[];
|
||||
documents: DeclarativeConfig[];
|
||||
warnings: Warning[];
|
||||
}
|
||||
|
||||
export interface KongForKubernetesResult {
|
||||
type: 'kong-for-kubernetes';
|
||||
label: string;
|
||||
documents: (KubernetesConfig | KubernetesPluginConfig | KubernetesMethodConfig)[];
|
||||
warnings: {
|
||||
severity: number;
|
||||
message: string;
|
||||
range: {};
|
||||
}[];
|
||||
documents: K8sManifest[];
|
||||
warnings: Warning[];
|
||||
}
|
||||
|
||||
export type ConversionResult = DeclarativeConfigResult | KongForKubernetesResult;
|
||||
Reference in new issue
Block a user