Skip to content

Commit

Permalink
Merge pull request finos#166 from willosborne/top-level-nodes
Browse files Browse the repository at this point in the history
Top level nodes
  • Loading branch information
jpgough-ms authored Apr 22, 2024
2 parents e393dc9 + c462006 commit 91d9d55
Show file tree
Hide file tree
Showing 3 changed files with 297 additions and 18 deletions.
70 changes: 69 additions & 1 deletion cli/src/commands/generate/generate.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ const {
getPropertyValue,
instantiateNodes,
instantiateRelationships,
instantiateNodeInterfaces
instantiateNodeInterfaces,
instantiateAdditionalTopLevelProperties
} = exportedForTesting;

describe('getPropertyValue', () => {
Expand Down Expand Up @@ -73,6 +74,8 @@ describe('getPropertyValue', () => {
});
});



function getSamplePatternNode(properties: any): any {
return {
properties: {
Expand Down Expand Up @@ -313,6 +316,71 @@ describe('instantiateRelationships', () => {
});
});

describe('instantiateAdditionalTopLevelProperties', () => {
it('instantiate an additional top level array property', () => {
const pattern = {
properties: {
'extra-property': {
properties: {
values: {
type: 'array'
}
}
}
}
};

expect(instantiateAdditionalTopLevelProperties(pattern))
.toEqual({
'extra-property': {
values: [ '{{ VALUES }}' ]
}
});
});

it('instantiate an additional top level const property', () => {
const pattern = {
properties: {
'extra': {
properties: {
'extra-property': {
const: 'value here'
}
}
}
}
};

expect(instantiateAdditionalTopLevelProperties(pattern))
.toEqual({
'extra': {
'extra-property': 'value here'
}
});
});

it('instantiate an additional top level string property', () => {
const pattern = {
properties: {
'extra': {
properties: {
'extra-property': {
'type': 'string'
}
}
}
}
};

expect(instantiateAdditionalTopLevelProperties(pattern))
.toEqual({
extra: {
'extra-property': '{{ EXTRA_PROPERTY }}'
}
});
});
});


describe('runGenerate', () => {
let tempDirectoryPath;
Expand Down
61 changes: 44 additions & 17 deletions cli/src/commands/generate/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ function getStringPlaceholder(name: string): string {
return '{{ ' + name.toUpperCase().replaceAll('-', '_') + ' }}';
}

function getPropertyValue(keyName: string, detail: any) : any {
function getPropertyValue(keyName: string, detail: any): any {
if ('const' in detail) {
return detail['const'];
}
Expand All @@ -41,8 +41,8 @@ function getPropertyValue(keyName: string, detail: any) : any {
return -1;
}
if (propertyType === 'array') {
return [
getStringPlaceholder(keyName)
return [
getStringPlaceholder(keyName)
];
}
}
Expand All @@ -51,7 +51,7 @@ function getPropertyValue(keyName: string, detail: any) : any {
function instantiateNodeInterfaces(detail: any): any[] {
const interfaces = [];
if (!('prefixItems' in detail)) {
console.error('No items in interfaces block.');
logger.error('No items in interfaces block.');
return [];
}

Expand All @@ -72,6 +72,20 @@ function instantiateNodeInterfaces(detail: any): any[] {
return interfaces;
}

function instantiateNode(node: any): any {
const out = {};
for (const [key, detail] of Object.entries(node['properties'])) {
if (key === 'interfaces') {
const interfaces = instantiateNodeInterfaces(detail);
out['interfaces'] = interfaces;
}
else {
out[key] = getPropertyValue(key, detail);
}
}
return out;
}

function instantiateNodes(pattern: any): any {
const nodes = pattern?.properties?.nodes?.prefixItems;
if (!nodes) {
Expand All @@ -88,18 +102,7 @@ function instantiateNodes(pattern: any): any {
continue;
}

const out = {};
for (const [key, detail] of Object.entries(node['properties'])) {
if (key === 'interfaces') {
const interfaces = instantiateNodeInterfaces(detail);
out['interfaces'] = interfaces;
}
else {
out[key] = getPropertyValue(key, detail);
}
}

outputNodes.push(out);
outputNodes.push(instantiateNode(node));
}
return outputNodes;
}
Expand Down Expand Up @@ -132,22 +135,46 @@ function instantiateRelationships(pattern: any): any {
return outputRelationships;
}

function instantiateAdditionalTopLevelProperties(pattern: any): any {
const properties = pattern?.properties;
if (!properties) {
logger.error('Warning: pattern has no properties defined.');
return [];
}

const extraProperties = {};
for (const [additionalProperty, detail] of Object.entries(properties)) {
// additional properties only
if (['nodes', 'relationships'].includes(additionalProperty)) {
continue;
}

// TODO
extraProperties[additionalProperty] = instantiateNode(detail);
}

return extraProperties;
}

export const exportedForTesting = {
getPropertyValue,
instantiateNodes,
instantiateRelationships,
instantiateNodeInterfaces
instantiateNodeInterfaces,
instantiateAdditionalTopLevelProperties
};

export function generate(patternPath: string, debug: boolean): CALMInstantiation {
logger = initLogger(debug);
const pattern = loadFile(patternPath);
const outputNodes = instantiateNodes(pattern);
const relationshipNodes = instantiateRelationships(pattern);
const additionalProperties = instantiateAdditionalTopLevelProperties(pattern);

const final = {
'nodes': outputNodes,
'relationships': relationshipNodes,
...additionalProperties // object spread operator to insert additional props at top level
};

return final;
Expand Down
184 changes: 184 additions & 0 deletions cli/test_fixtures/additional-props.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
{
"$schema": "https://raw.githubusercontent.com/finos-labs/architecture-as-code/main/calm/draft/2024-03/meta/calm.json",
"$id": "https://raw.githubusercontent.com/finos-labs/architecture-as-code/main/calm/pattern/api-gateway",
"title": "API Gateway Pattern",
"type": "object",
"properties": {
"nodes": {
"type": "array",
"minItems": 3,
"prefixItems": [
{
"$ref": "https://raw.githubusercontent.com/finos-labs/architecture-as-code/main/calm/draft/2024-03/meta/core.json#/defs/node",
"properties": {
"ingress-host": {
"type": "string"
},
"ingress-port": {
"type": "integer"
},
"well-known-endpoint": {
"type": "string"
},
"description": {
"const": "The API Gateway used to verify authorization and access to downstream system"
},
"type": {
"const": "system"
},
"name": {
"const": "API Gateway"
},
"unique-id": {
"const": "api-gateway"
}
},
"required": [
"ingress-host",
"ingress-port",
"well-known-endpoint"
]
},
{
"$ref": "https://raw.githubusercontent.com/finos-labs/architecture-as-code/main/calm/draft/2024-03/meta/core.json#/defs/node",
"properties": {
"description": {
"const": "The API Consumer making an authenticated and authorized request"
},
"type": {
"const": "system"
},
"name": {
"const": "Python Based API Consumer"
},
"unique-id": {
"const": "api-consumer"
}
}
},
{
"$ref": "https://raw.githubusercontent.com/finos-labs/architecture-as-code/main/calm/draft/2024-03/meta/core.json#/defs/node",
"properties": {
"host": {
"type": "string"
},
"port": {
"type": "integer"
},
"description": {
"const": "The API Producer serving content"
},
"type": {
"const": "system"
},
"name": {
"const": "Java Based API Producer"
},
"unique-id": {
"const": "api-producer"
}
},
"required": [
"host",
"port"
]
},
{
"$ref": "https://raw.githubusercontent.com/finos-labs/architecture-as-code/main/calm/draft/2024-03/meta/core.json#/defs/node",
"properties": {
"description": {
"const": "The Identity Provider used to verify the bearer token"
},
"type": {
"const": "system"
},
"name": {
"const": "Identity Provider"
},
"unique-id": {
"const": "idp"
}
}
}
]
},
"relationships": {
"type": "array",
"minItems": 3,
"prefixItems": [
{
"$ref": "https://raw.githubusercontent.com/finos-labs/architecture-as-code/main/calm/draft/2024-03/meta/core.json#/defs/relationship",
"properties": {
"unique-id": {
"const": "api-consumer-api-gateway"
},
"relationship-type": {
"const": {
"connects": {
"source": "api-consumer",
"destination": "api-gateway"
}
}
},
"parties": {
},
"protocol": {
"const": "HTTPS"
},
"authentication": {
"const": "OAuth2"
}
}
},
{
"$ref": "https://raw.githubusercontent.com/finos-labs/architecture-as-code/main/calm/draft/2024-03/meta/core.json#/defs/relationship",
"properties": {
"unique-id": {
"const": "api-gateway-idp"
},
"relationship-type": {
"const": {
"connects": {
"source": "api-gateway",
"destination": "idp"
}
}
},
"protocol": {
"const": "HTTPS"
}
}
},
{
"$ref": "https://raw.githubusercontent.com/finos-labs/architecture-as-code/main/calm/draft/2024-03/meta/core.json#/defs/relationship",
"properties": {
"unique-id": {
"const": "api-gateway-api-producer"
},
"relationship-type": {
"const": {
"connects": {
"source": "api-gateway",
"destination": "api-producer"
}
}
},
"protocol": {
"const": "HTTPS"
}
}
}
]
},
"extra-property-constant": {
"const": "constant value"
},
"extra-property-array": {
"type": "array"
}
},
"required": [
"nodes",
"relationships"
]
}

0 comments on commit 91d9d55

Please sign in to comment.