Skip to content

Commit 9540993

Browse files
CLOUDP-283086: Restructure and identify resource
1 parent 635851c commit 9540993

File tree

6 files changed

+114
-52
lines changed

6 files changed

+114
-52
lines changed

tools/ipa/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ setup: deps devtools ## Set up dev env
2121
.PHONY: linterr
2222
linterr: ## Run spectral linter on foas
2323
@echo "==> Running spectral linter"
24-
npx -- @stoplight/spectral-cli@"${SPECTRAL_VERSION}" lint ../../openapi/v2.yaml --ruleset=ruleset.yaml
24+
npx -- @stoplight/spectral-cli@"${SPECTRAL_VERSION}" lint ../../openapi/v2.yaml --ruleset=ipa-spectral.yaml -v
2525

2626
.PHONY: lintwarn
2727
lintwarn: ## Run spectral linter on foas
2828
@echo "==> Running spectral linter"
29-
npx -- @stoplight/spectral-cli@"${SPECTRAL_VERSION}" lint ../../openapi/v2.yaml --ruleset=ruleset.yaml --fail-severity=warn
29+
npx -- @stoplight/spectral-cli@"${SPECTRAL_VERSION}" lint ../../openapi/v2.yaml --ruleset=ipa-spectral --fail-severity=warn -v
3030

3131
.PHONY: help
3232
.DEFAULT_GOAL := help

tools/ipa/functions/hasDescription.js

Lines changed: 0 additions & 10 deletions
This file was deleted.

tools/ipa/ipa-spectral.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
extends:
2+
- ./rulesets/IPA-104.yaml

tools/ipa/ruleset.yaml

Lines changed: 0 additions & 40 deletions
This file was deleted.

tools/ipa/rulesets/IPA-104.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# IPA-104: Get
2+
# http://go/ipa/104
3+
4+
functions:
5+
- eachResourceHasGetMethod
6+
7+
rules:
8+
xgen-IPA-104-resource-has-GET:
9+
description: "APIs must provide a get method for resources. http://go/ipa/104"
10+
message: "{{error}} http://go/ipa/117"
11+
severity: error
12+
given: "$.paths"
13+
then:
14+
field: "@key"
15+
function: "eachResourceHasGetMethod"
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
const ERROR_MESSAGE = "APIs must provide a get method for resources."
2+
3+
export default (input, _, context) => {
4+
if (isChild(input) || isCustomMethod(input)) {
5+
return
6+
}
7+
8+
const oas = context.documentInventory.resolved
9+
10+
const resourcePaths = getResourcePaths(input, Object.keys(oas.paths))
11+
12+
if (isSingletonResource(resourcePaths)) {
13+
// Singleton resource, may have custom methods
14+
if (!hasGetMethod(oas.paths[resourcePaths[0]])) {
15+
return [
16+
{
17+
message: ERROR_MESSAGE
18+
}
19+
]
20+
}
21+
} else if (isNormalResource(resourcePaths)) {
22+
// Normal resource, may have custom methods
23+
if (!hasGetMethod(oas.paths[resourcePaths[1]])) {
24+
return [
25+
{
26+
message: ERROR_MESSAGE
27+
}
28+
]
29+
}
30+
}
31+
}
32+
33+
function isChild(path) {
34+
return path.endsWith("}")
35+
}
36+
37+
function isCustomMethod(path) {
38+
return path.includes(":")
39+
}
40+
41+
/**
42+
* Get all paths for a resource based on the parent path
43+
*
44+
* @param parent the parent path string
45+
* @param allPaths all paths as an array of strings
46+
* @returns {*} a string array of all paths for a resource, including the parent
47+
*/
48+
function getResourcePaths(parent, allPaths) {
49+
const childPathPattern = new RegExp(`^${parent}/{[a-zA-Z]+}$`);
50+
const customMethodPattern = new RegExp(`^${parent}/{[a-zA-Z]+}:+[a-zA-Z]+$`);
51+
return allPaths.filter(p => parent === p || childPathPattern.test(p) || customMethodPattern.test(p));
52+
}
53+
54+
/**
55+
* Checks if a resource is a singleton resource based on the paths for the
56+
* resource. The resource may have custom methods.
57+
*
58+
* @param resourcePaths all paths for the resource as an array of strings
59+
* @returns {boolean}
60+
*/
61+
function isSingletonResource(resourcePaths) {
62+
if (resourcePaths.length === 1) {
63+
return true
64+
}
65+
const additionalPaths = resourcePaths.slice(1)
66+
return !additionalPaths.some((p) => !isCustomMethod(p))
67+
}
68+
69+
/**
70+
* Checks if a resource is a normal resource based on the paths for the
71+
* resource. The resource may have custom methods.
72+
*
73+
* @param resourcePaths all paths for the resource as an array of strings
74+
* @returns {boolean}
75+
*/
76+
function isNormalResource(resourcePaths) {
77+
if (resourcePaths.length === 2 && isChild(resourcePaths[1])) {
78+
return true
79+
}
80+
if (resourcePaths.length < 3 || !isChild(resourcePaths[1])) {
81+
return false
82+
}
83+
const additionalPaths = resourcePaths.slice(2)
84+
return !additionalPaths.some((p) => !isCustomMethod(p))
85+
}
86+
87+
/**
88+
* Checks if a path object has a GET method
89+
*
90+
* @param pathObject the path object to evaluate
91+
* @returns {boolean}
92+
*/
93+
function hasGetMethod(pathObject) {
94+
return Object.keys(pathObject).some((o) => o === "get")
95+
}

0 commit comments

Comments
 (0)