Foundation for standard status values
Signed-off-by: Fredrik Adelöw <freben@gmail.com>
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
---
|
||||
'@backstage/catalog-client': patch
|
||||
'@backstage/catalog-model': patch
|
||||
'@backstage/plugin-catalog-backend': patch
|
||||
---
|
||||
|
||||
Foundation for standard entity status values
|
||||
@@ -7,6 +7,9 @@
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { EntityName } from '@backstage/catalog-model';
|
||||
import { Location as Location_2 } from '@backstage/catalog-model';
|
||||
import { SerializedError } from '@backstage/errors';
|
||||
import { UNSTABLE_EntityStatusLevel } from '@backstage/catalog-model';
|
||||
import { UNSTABLE_EntityStatusValue } from '@backstage/catalog-model';
|
||||
|
||||
// @public (undocumented)
|
||||
export type AddLocationRequest = {
|
||||
@@ -76,6 +79,21 @@ export type CatalogListResponse<T> = {
|
||||
items: T[];
|
||||
};
|
||||
|
||||
// @public
|
||||
export const ENTITY_STATUS_CATALOG_PROCESSING_KEY = "backstage.io/catalog-processing";
|
||||
|
||||
// @public
|
||||
export type UNSTABLE_CatalogProcessingStatus = UNSTABLE_EntityStatusValue & {
|
||||
items?: UNSTABLE_CatalogProcessingStatusItem[];
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export type UNSTABLE_CatalogProcessingStatusItem = {
|
||||
status: UNSTABLE_EntityStatusLevel;
|
||||
message?: string;
|
||||
error?: SerializedError;
|
||||
};
|
||||
|
||||
|
||||
// (No @packageDocumentation comment for this package)
|
||||
|
||||
|
||||
@@ -18,7 +18,8 @@ import { Entity } from '@backstage/catalog-model';
|
||||
import { rest } from 'msw';
|
||||
import { setupServer } from 'msw/node';
|
||||
import { CatalogClient } from './CatalogClient';
|
||||
import { CatalogListResponse, DiscoveryApi } from './types';
|
||||
import { CatalogListResponse } from './types/api';
|
||||
import { DiscoveryApi } from './types/discovery';
|
||||
|
||||
const server = setupServer();
|
||||
const token = 'fake-token';
|
||||
|
||||
@@ -31,8 +31,8 @@ import {
|
||||
CatalogEntitiesRequest,
|
||||
CatalogListResponse,
|
||||
CatalogRequestOptions,
|
||||
DiscoveryApi,
|
||||
} from './types';
|
||||
} from './types/api';
|
||||
import { DiscoveryApi } from './types/discovery';
|
||||
|
||||
export class CatalogClient implements CatalogApi {
|
||||
private readonly discoveryApi: DiscoveryApi;
|
||||
|
||||
@@ -15,10 +15,4 @@
|
||||
*/
|
||||
|
||||
export { CatalogClient } from './CatalogClient';
|
||||
export type {
|
||||
AddLocationRequest,
|
||||
AddLocationResponse,
|
||||
CatalogApi,
|
||||
CatalogEntitiesRequest,
|
||||
CatalogListResponse,
|
||||
} from './types';
|
||||
export * from './types';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2021 Spotify AB
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -81,10 +81,3 @@ export type AddLocationResponse = {
|
||||
location: Location;
|
||||
entities: Entity[];
|
||||
};
|
||||
|
||||
/**
|
||||
* This is a copy of the core DiscoveryApi, to avoid importing core.
|
||||
*/
|
||||
export type DiscoveryApi = {
|
||||
getBaseUrl(pluginId: string): Promise<string>;
|
||||
};
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2021 Spotify AB
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This is a copy of the core DiscoveryApi, to avoid importing core.
|
||||
*/
|
||||
export type DiscoveryApi = {
|
||||
getBaseUrl(pluginId: string): Promise<string>;
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2021 Spotify AB
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export type {
|
||||
AddLocationRequest,
|
||||
AddLocationResponse,
|
||||
CatalogApi,
|
||||
CatalogEntitiesRequest,
|
||||
CatalogListResponse,
|
||||
} from './api';
|
||||
export { ENTITY_STATUS_CATALOG_PROCESSING_KEY } from './status';
|
||||
export type {
|
||||
UNSTABLE_CatalogProcessingStatus,
|
||||
UNSTABLE_CatalogProcessingStatusItem,
|
||||
} from './status';
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2021 Spotify AB
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
UNSTABLE_EntityStatusLevel,
|
||||
UNSTABLE_EntityStatusValue,
|
||||
} from '@backstage/catalog-model';
|
||||
import { SerializedError } from '@backstage/errors';
|
||||
|
||||
/*
|
||||
* This is the entity status field that's emitted by the catalog processing
|
||||
* engine, to inform about the status of an entity.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* "status": {
|
||||
* "backstage.io/catalog-processing": {
|
||||
* "status": "error",
|
||||
* "items": [
|
||||
* {
|
||||
* "status": "error",
|
||||
* "error": {
|
||||
* "name": "InputError",
|
||||
* "message": "Syntax error: ..."
|
||||
* }
|
||||
* }
|
||||
* ]
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
|
||||
/**
|
||||
* The entity `status` key for the status of the processing engine in regards
|
||||
* to entity.
|
||||
*/
|
||||
export const ENTITY_STATUS_CATALOG_PROCESSING_KEY =
|
||||
'backstage.io/catalog-processing';
|
||||
|
||||
/**
|
||||
* The status value for the `backstage.io/catalog-processing` key.
|
||||
*/
|
||||
export type UNSTABLE_CatalogProcessingStatus = UNSTABLE_EntityStatusValue & {
|
||||
items?: UNSTABLE_CatalogProcessingStatusItem[];
|
||||
};
|
||||
|
||||
export type UNSTABLE_CatalogProcessingStatusItem = {
|
||||
status: UNSTABLE_EntityStatusLevel;
|
||||
message?: string;
|
||||
error?: SerializedError;
|
||||
};
|
||||
@@ -528,6 +528,15 @@ export interface TemplateEntityV1beta2 extends Entity {
|
||||
// @public (undocumented)
|
||||
export const templateEntityV1beta2Validator: KindValidator;
|
||||
|
||||
// @public
|
||||
export type UNSTABLE_EntityStatusLevel = 'ok' | 'info' | 'warning' | 'error';
|
||||
|
||||
// @public
|
||||
export type UNSTABLE_EntityStatusValue = {
|
||||
status: UNSTABLE_EntityStatusLevel;
|
||||
message?: string;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
interface UserEntityV1alpha1 extends Entity {
|
||||
// (undocumented)
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
*/
|
||||
|
||||
export {
|
||||
EDIT_URL_ANNOTATION,
|
||||
ENTITY_DEFAULT_NAMESPACE,
|
||||
ENTITY_META_GENERATED_FIELDS,
|
||||
VIEW_URL_ANNOTATION,
|
||||
EDIT_URL_ANNOTATION,
|
||||
} from './constants';
|
||||
export type {
|
||||
Entity,
|
||||
@@ -36,6 +36,10 @@ export {
|
||||
serializeEntityRef,
|
||||
stringifyEntityRef,
|
||||
} from './ref';
|
||||
export type {
|
||||
UNSTABLE_EntityStatusLevel,
|
||||
UNSTABLE_EntityStatusValue,
|
||||
} from './status';
|
||||
export {
|
||||
entityHasChanges,
|
||||
generateEntityEtag,
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2021 Spotify AB
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Each entity status entry has a level, describing its severity.
|
||||
*/
|
||||
export type UNSTABLE_EntityStatusLevel =
|
||||
| 'ok' // Everything is OK
|
||||
| 'info' // Only informative data
|
||||
| 'warning' // Warnings were found
|
||||
| 'error'; // Errors were found
|
||||
|
||||
/**
|
||||
* Reserved root fields in all `status` object values.
|
||||
*/
|
||||
export type UNSTABLE_EntityStatusValue = {
|
||||
status: UNSTABLE_EntityStatusLevel;
|
||||
message?: string;
|
||||
};
|
||||
@@ -31,6 +31,7 @@
|
||||
"dependencies": {
|
||||
"@azure/msal-node": "^1.0.0-beta.3",
|
||||
"@backstage/backend-common": "^0.8.1",
|
||||
"@backstage/catalog-client": "^0.3.11",
|
||||
"@backstage/catalog-model": "^0.7.10",
|
||||
"@backstage/config": "^0.1.5",
|
||||
"@backstage/errors": "^0.1.1",
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
import { stringifyEntityRef } from '@backstage/catalog-model';
|
||||
import { serializeError } from '@backstage/errors';
|
||||
import { Logger } from 'winston';
|
||||
import { ProcessingDatabase } from './database/types';
|
||||
import { Stitcher } from './Stitcher';
|
||||
@@ -128,7 +129,7 @@ export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine {
|
||||
id,
|
||||
processedEntity: result.completedEntity,
|
||||
state: result.state,
|
||||
errors: JSON.stringify(result.errors),
|
||||
errors: JSON.stringify(result.errors.map(e => serializeError(e))),
|
||||
relations: result.relations,
|
||||
deferredEntities: result.deferredEntities,
|
||||
});
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
import { getVoidLogger } from '@backstage/backend-common';
|
||||
import { Knex } from 'knex';
|
||||
import { ENTITY_STATUS_CATALOG_PROCESSING_KEY } from '@backstage/catalog-client';
|
||||
import { DatabaseManager } from './database/DatabaseManager';
|
||||
import {
|
||||
DbRefreshStateReferencesRow,
|
||||
@@ -92,7 +93,7 @@ describe('Stitcher', () => {
|
||||
},
|
||||
],
|
||||
status: {
|
||||
'backstage.io/catalog-processing': {},
|
||||
[ENTITY_STATUS_CATALOG_PROCESSING_KEY]: { status: 'ok' },
|
||||
},
|
||||
apiVersion: 'a',
|
||||
kind: 'k',
|
||||
@@ -175,7 +176,7 @@ describe('Stitcher', () => {
|
||||
},
|
||||
]),
|
||||
status: {
|
||||
'backstage.io/catalog-processing': {},
|
||||
[ENTITY_STATUS_CATALOG_PROCESSING_KEY]: { status: 'ok' },
|
||||
},
|
||||
apiVersion: 'a',
|
||||
kind: 'k',
|
||||
|
||||
@@ -14,9 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
ENTITY_STATUS_CATALOG_PROCESSING_KEY,
|
||||
UNSTABLE_CatalogProcessingStatusItem,
|
||||
} from '@backstage/catalog-client';
|
||||
import { Entity, parseEntityRef } from '@backstage/catalog-model';
|
||||
import { JsonObject } from '@backstage/config';
|
||||
import { ConflictError } from '@backstage/errors';
|
||||
import { ConflictError, SerializedError } from '@backstage/errors';
|
||||
import { createHash } from 'crypto';
|
||||
import stableStringify from 'fast-json-stable-stringify';
|
||||
import { Knex } from 'knex';
|
||||
@@ -36,10 +39,6 @@ export type DbFinalEntitiesRow = {
|
||||
final_entity: string;
|
||||
};
|
||||
|
||||
type ProcessingStatus = {
|
||||
errors?: JsonObject[];
|
||||
};
|
||||
|
||||
function generateStableHash(entity: Entity) {
|
||||
return createHash('sha1')
|
||||
.update(stableStringify({ ...entity }))
|
||||
@@ -139,7 +138,7 @@ export class Stitcher {
|
||||
// it
|
||||
const entity = JSON.parse(processedEntity) as Entity;
|
||||
const isOrphan = Number(incomingReferenceCount) === 0;
|
||||
const processingStatus: ProcessingStatus = {};
|
||||
let statusItems: UNSTABLE_CatalogProcessingStatusItem[] = [];
|
||||
|
||||
if (isOrphan) {
|
||||
this.logger.debug(`${entityRef} is an orphan`);
|
||||
@@ -149,9 +148,12 @@ export class Stitcher {
|
||||
};
|
||||
}
|
||||
if (errors) {
|
||||
const parsedErrors = JSON.parse(errors);
|
||||
const parsedErrors = JSON.parse(errors) as SerializedError[];
|
||||
if (Array.isArray(parsedErrors) && parsedErrors.length) {
|
||||
processingStatus.errors = parsedErrors;
|
||||
statusItems = parsedErrors.map(e => ({
|
||||
status: 'error',
|
||||
error: e,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,7 +167,9 @@ export class Stitcher {
|
||||
}));
|
||||
entity.status = {
|
||||
...entity.status,
|
||||
'backstage.io/catalog-processing': processingStatus,
|
||||
[ENTITY_STATUS_CATALOG_PROCESSING_KEY]: statusItems.length
|
||||
? { status: 'error', items: statusItems }
|
||||
: { status: 'ok' },
|
||||
};
|
||||
|
||||
// If the output entity was actually not changed, just abort
|
||||
|
||||
Reference in New Issue
Block a user