Skip to content

Commit

Permalink
Merge pull request #2538 from newrelic/zstix/NR-268433_qs_json_schema
Browse files Browse the repository at this point in the history
Introduce JSON schemas for quickstart artifacts
  • Loading branch information
zstix authored Sep 4, 2024
2 parents 49da4de + 465bfca commit ad9782a
Show file tree
Hide file tree
Showing 6 changed files with 429 additions and 2 deletions.
7 changes: 7 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# Documentation

Each file in this directory (minus this readme) is generated from New Relic NerdGraph GraphQL schema.

## Validation

Every quickstart, datasource, alert, and dashboard is bundled into a single artifact and validated against our [schema](../utils/schema/artifact.json) for correctness.

> [!IMPORTANT]
> Please ensure that _all_ feature flags are removed from a datasource before it is referenced in a quickstart. Otherwise, the datasource will not be properly associated.
2 changes: 1 addition & 1 deletion utils/lib/DataSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ class DataSource extends Component<DataSourceConfig, string> {
}
}

const getAllDataSourceFiles = (
export const getAllDataSourceFiles = (
basePath: string = path.join(__dirname, '..', '..')
): string[] =>
glob.sync(path.join(basePath, 'data-sources', '**', 'config.+(yml|yaml)'));
Expand Down
3 changes: 2 additions & 1 deletion utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
"create-preview-links": "ts-node create-preview-links.ts",
"set-alert-policy-required-datasources": "ts-node set-alert-policy-required-datasources.ts",
"set-dashboards-required-datasources": "ts-node set-dashboards-required-datasources.ts",
"release": "ts-node release.ts"
"release": "ts-node release.ts",
"add-datasource-ids": "cd ./schema && ts-node add-datasource-ids.ts"
},
"dependencies": {
"@actions/core": "^1.10.0",
Expand Down
83 changes: 83 additions & 0 deletions utils/schema/add-datasource-ids.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import * as fs from 'fs';
import * as yaml from 'js-yaml';

import type { DataSourceConfig } from '../types/DataSourceConfig';

import { getAllDataSourceFiles } from '../lib/DataSource';

const ARTIFACT_SCHEMA_PATH = './artifact.json';
const CORE_DATASOURCE_IDS_PATH = './core-datasource-ids.json';
const DATASOURCE_BASE_PATH = '../../';

type ArtifactSchema = {
properties: {
dataSourceIds: {
enum: string[];
};
};
};

const getCommunityDataSourceIds = (): string[] => {
const allDataSources = getAllDataSourceFiles(DATASOURCE_BASE_PATH).map(
(p) => ({
filePath: p,
content: yaml.load(
fs.readFileSync(p).toString('utf-8')
) as DataSourceConfig,
})
);

return allDataSources
.map((dataSource) => dataSource.content?.id)
.filter(Boolean);
};

const getCoreDataSourceIds = (): string[] => {
return yaml.load(
fs.readFileSync(CORE_DATASOURCE_IDS_PATH).toString('utf8')
) as string[];
};

const loadSchema = (filepath: string): ArtifactSchema => {
return yaml.load(
fs.readFileSync(filepath).toString('utf8')
) as ArtifactSchema;
};

const updateSchema = (
schema: ArtifactSchema,
ids: string[]
): ArtifactSchema => {
return {
...schema,
properties: {
...schema.properties,
dataSourceIds: { enum: ids },
},
};
};

const saveSchema = (schema: ArtifactSchema, path: string): void => {
fs.writeFileSync(path, JSON.stringify(schema, null, 2));
};

const main = (): void => {
const communityIds = getCommunityDataSourceIds();
console.log(`[*] Found ${communityIds.length} community dataSources`);

const coreIds = getCoreDataSourceIds();
console.log(`[*] Found ${coreIds.length} core dataSources`);

console.log('[*] Loading schema');
const schema = loadSchema(ARTIFACT_SCHEMA_PATH);

console.log('[*] Updating enum');
const updatedSchema = updateSchema(schema, [...communityIds, ...coreIds]);

console.log('[*] Saving updated schema');
saveSchema(updatedSchema, ARTIFACT_SCHEMA_PATH);
};

if (require.main === module) {
main();
}
196 changes: 196 additions & 0 deletions utils/schema/artifact.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
{
"$schema": "http://json-schema.org/draft-07/schema",

"type": "object",
"properties": {
"quickstarts": {
"type": "array",
"items": { "$ref": "#/definitions/quickstart" }
},
"dataSources": {
"type": "array",
"items": { "$ref": "#/definitions/dataSource" }
},
"alerts": {
"type": "array",
"items": { "$ref": "#/definitions/alert" }
},
"dashboards": {
"type": "array",
"items": { "$ref": "#/definitions/dashboard" }
},
"dataSourceIds": {
"type": "array", "items": { "type": "string" }
}
},
"required": [
"quickstarts",
"dataSources",
"alerts",
"dashboards",
"dataSourceIds"
],
"additionalProperties": false,

"definitions": {
"quickstart": {
"type": "object",
"properties": {
"id": { "type": "string" },
"description": { "type": "string" },
"summary": { "type": "string" },
"title": { "type": "string" },
"authors": {
"type": "array", "items": { "type": "string" }
},
"documentation": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": { "type": "string" },
"description": { "type": "string" },
"url": { "type": "string" }
},
"required": ["name", "description", "url"],
"additionalProperties": false
}
},
"level": { "enum": ["New Relic", "Community", "Verified"] },
"icon": { "type": "string" },
"keywords": {
"type": "array", "items": { "type": "string" }
},
"slug": { "type": "string" },
"alertPolicies": {
"type": "array", "items": { "type": "string" }
},
"dashboards": {
"type": "array", "items": { "type": "string" }
},
"dataSourceIds": {
"type": "array", "items": { "type": "string" }
}
},
"required": [
"id",
"description",
"summary",
"title",
"authors",
"documentation",
"level",
"icon"
],
"additionalProperties": false
},

"dataSource": {
"type": "object",
"properties": {
"id": { "type": "string" },
"displayName": { "type": "string" },
"description": { "type": "string" },
"install": {
"type": "object",
"properties": {
"primary": { "$ref": "#/definitions/installDirective" },
"fallback": { "$ref": "#/definitions/installDirective" }
},
"required": ["primary"],
"additionalProperties": false
},
"keywords": {
"type": "array", "items": { "type": "string" }
},
"categoryTerms": {
"type": "array", "items": { "type": "string" }
},
"icon": { "type": "string" }
},
"required": ["id", "displayName", "install"],
"additionalProperties": false
},

"installDirective": {
"enum": [
{
"type": "object",
"properties": {
"link": {
"type": "object",
"properties": {
"url": { "type": "string" }
},
"required": ["url"],
"additionalProperties": false
}
},
"required": ["link"],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"nerdlet": {
"type": "object",
"properties": {
"nerdletId": { "type": "string" },
"nerdletState": { "type": "object" },
"requiresAccount": { "type": "boolean" }
},
"required": ["nerdletId", "nerdletState", "requiresAccount"],
"additionalProperties": false
}
},
"required": "nerdlet",
"additionalProperties": false
}
]
},

"alert": {
"type": "object",
"properties": {
"name": { "type": "string" },
"description": { "type": "string" },
"type": { "enum": ["BASELINE", "STATIC"] },
"nrql": { "type": "string" },
"runbookUrl": { "type": "string" },
"violationTimeLimitSeconds": { "type": "number" },
"enabled": { "type": "boolean" },
"terms": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"properties": {
"duration": { "type": "number", "minimum": 5, "maximum": 120 },
"priority": { "enum": ["CRITICAL", "WARNING"] },
"operator": { "enum": ["ABOVE", "BELOW", "EQUAL"] },
"threshold": { "type": "number", "minimum": 0 },
"thresholdDuration": { "type": "number", "minimum": 0 },
"thresholdOccurances": { "enum": ["ALL", "AT_LEAST_ONCE"] }
},
"required": ["duration"],
"additionalProperties": true
}
}
},
"required": ["name", "description", "type"],
"additionalProperties": true
},

"dashboard": {
"type": "object",
"properties": {
"name": { "type": "string" },
"pages": { "type": "array", "minItems": 1 },
"description": { "type": "string" },
"variables": { "type": "array" }
},
"required": ["name", "pages"],
"additionalProperties": false
}
}
}
Loading

0 comments on commit ad9782a

Please sign in to comment.