Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 162 additions & 0 deletions tools/spectral/ipa/__tests__/IPA132GetMethodMustNotBeLro.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
import testRule from './__helpers__/testRule';
import { DiagnosticSeverity } from '@stoplight/types';

const ERROR_MESSAGE =
'The Get method must not be a long-running operation. A Get returns the current state of a resource that already exists on the server.';

const syncGet = {
responses: {
200: {},
},
};

const lroGet = {
responses: {
202: {
description: 'Accepted',
headers: {
Location: {
schema: { type: 'string', format: 'uri' },
},
},
},
},
};

testRule('xgen-IPA-132-get-method-must-not-be-lro', [
{
name: 'valid synchronous Get methods',
document: {
paths: {
'/api/atlas/v2/resourceName/{pathParam}': {
get: syncGet,
},
// Singleton resource
'/api/atlas/v2/resourceName/{pathParam}/settings': {
get: syncGet,
},
},
},
errors: [],
},
{
name: 'methods that are not Get methods are ignored',
document: {
paths: {
// List method, covered by xgen-IPA-132-list-method-must-not-be-lro
'/api/atlas/v2/resourceName': {
get: lroGet,
},
// Custom method
'/api/atlas/v2/resourceName/{pathParam}:customMethod': {
get: lroGet,
},
},
},
errors: [],
},
{
name: 'invalid Get method declaring a 202 response',
document: {
paths: {
'/api/atlas/v2/resourceName/{pathParam}': {
get: lroGet,
},
},
},
errors: [
{
code: 'xgen-IPA-132-get-method-must-not-be-lro',
message: ERROR_MESSAGE,
path: ['paths', '/api/atlas/v2/resourceName/{pathParam}', 'get', 'responses', '202'],
severity: DiagnosticSeverity.Warning,
},
],
},
{
name: 'invalid singleton Get method declaring a 202 response',
document: {
paths: {
'/api/atlas/v2/resourceName/{pathParam}/settings': {
get: lroGet,
},
},
},
errors: [
{
code: 'xgen-IPA-132-get-method-must-not-be-lro',
message: ERROR_MESSAGE,
path: ['paths', '/api/atlas/v2/resourceName/{pathParam}/settings', 'get', 'responses', '202'],
severity: DiagnosticSeverity.Warning,
},
],
},
{
name: 'invalid Get method declaring a 202 response alongside a 200 response',
document: {
paths: {
'/api/atlas/v2/resourceName/{pathParam}': {
get: {
responses: {
200: {},
202: {},
},
},
},
},
},
errors: [
{
code: 'xgen-IPA-132-get-method-must-not-be-lro',
message: ERROR_MESSAGE,
path: ['paths', '/api/atlas/v2/resourceName/{pathParam}', 'get', 'responses', '202'],
severity: DiagnosticSeverity.Warning,
},
],
},
{
name: 'invalid Get methods with exceptions',
document: {
paths: {
'/api/atlas/v2/resourceName/{pathParam}': {
get: {
...lroGet,
'x-xgen-IPA-exception': {
'xgen-IPA-132-get-method-must-not-be-lro': 'reason',
},
},
},
},
},
errors: [],
},
{
name: 'compliant Get method does not need an exception',
document: {
paths: {
'/api/atlas/v2/resourceName/{pathParam}': {
get: {
...syncGet,
'x-xgen-IPA-exception': {
'xgen-IPA-132-get-method-must-not-be-lro': 'reason',
},
},
},
},
},
errors: [
{
code: 'xgen-IPA-132-get-method-must-not-be-lro',
message: 'This component adopts the rule and does not need an exception. Please remove the exception.',
path: [
'paths',
'/api/atlas/v2/resourceName/{pathParam}',
'get',
'x-xgen-IPA-exception',
'xgen-IPA-132-get-method-must-not-be-lro',
],
severity: DiagnosticSeverity.Warning,
},
],
},
]);
144 changes: 144 additions & 0 deletions tools/spectral/ipa/__tests__/IPA132ListMethodMustNotBeLro.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
import testRule from './__helpers__/testRule';
import { DiagnosticSeverity } from '@stoplight/types';

const ERROR_MESSAGE =
'The List method must not be a long-running operation. A List returns data from a collection that already exists on the server.';

const syncList = {
responses: {
200: {},
},
};

const lroList = {
responses: {
202: {
description: 'Accepted',
headers: {
Location: {
schema: { type: 'string', format: 'uri' },
},
},
},
},
};

testRule('xgen-IPA-132-list-method-must-not-be-lro', [
{
name: 'valid synchronous List methods',
document: {
paths: {
'/api/atlas/v2/resourceName': {
get: syncList,
},
},
},
errors: [],
},
{
name: 'methods that are not List methods are ignored',
document: {
paths: {
// Get method, covered by xgen-IPA-132-get-method-must-not-be-lro
'/api/atlas/v2/resourceName/{pathParam}': {
get: lroList,
},
// Singleton resource Get method
'/api/atlas/v2/resourceName/{pathParam}/settings': {
get: lroList,
},
// Custom method
'/api/atlas/v2/resourceName:customMethod': {
get: lroList,
},
},
},
errors: [],
},
{
name: 'invalid List method declaring a 202 response',
document: {
paths: {
'/api/atlas/v2/resourceName': {
get: lroList,
},
},
},
errors: [
{
code: 'xgen-IPA-132-list-method-must-not-be-lro',
message: ERROR_MESSAGE,
path: ['paths', '/api/atlas/v2/resourceName', 'get', 'responses', '202'],
severity: DiagnosticSeverity.Warning,
},
],
},
{
name: 'invalid List method declaring a 202 response alongside a 200 response',
document: {
paths: {
'/api/atlas/v2/resourceName': {
get: {
responses: {
200: {},
202: {},
},
},
},
},
},
errors: [
{
code: 'xgen-IPA-132-list-method-must-not-be-lro',
message: ERROR_MESSAGE,
path: ['paths', '/api/atlas/v2/resourceName', 'get', 'responses', '202'],
severity: DiagnosticSeverity.Warning,
},
],
},
{
name: 'invalid List methods with exceptions',
document: {
paths: {
'/api/atlas/v2/resourceName': {
get: {
...lroList,
'x-xgen-IPA-exception': {
'xgen-IPA-132-list-method-must-not-be-lro': 'reason',
},
},
},
},
},
errors: [],
},
{
name: 'compliant List method does not need an exception',
document: {
paths: {
'/api/atlas/v2/resourceName': {
get: {
...syncList,
'x-xgen-IPA-exception': {
'xgen-IPA-132-list-method-must-not-be-lro': 'reason',
},
},
},
},
},
errors: [
{
code: 'xgen-IPA-132-list-method-must-not-be-lro',
message: 'This component adopts the rule and does not need an exception. Please remove the exception.',
path: [
'paths',
'/api/atlas/v2/resourceName',
'get',
'x-xgen-IPA-exception',
'xgen-IPA-132-list-method-must-not-be-lro',
],
severity: DiagnosticSeverity.Warning,
},
],
},
]);
42 changes: 42 additions & 0 deletions tools/spectral/ipa/rulesets/IPA-132.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,14 @@ functions:
- IPA132OperationResponseMustUseStandardEnumValues
- IPA132OperationResponseMustDefineNestedObjectStructure
- IPA132OperationsShouldExposeStatusFields
- IPA132GetMethodMustNotBeLro
- IPA132ListMethodMustNotBeLro

aliases:
OperationResponseSchema:
- '$.components.schemas.OperationResponse'
GetOperationObject:
- '$.paths[*].get'

rules:
xgen-IPA-132-operations-endpoint-must-not-be-global:
Expand Down Expand Up @@ -283,3 +287,41 @@ rules:
objects:
- field: progress
properties: [completed, total, unit]

xgen-IPA-132-get-method-must-not-be-lro:
description: |
A Get method must not be a long-running operation. A Get returns the current state of a
single resource that already resides on the server.

##### Implementation details
Rule checks for the following conditions:

- Applies to GET methods on single resources and singleton resources
- The Get method must not declare a 202 response; a Get reads state that already exists on
the server, so there is no background work to track
- Operations with `x-xgen-IPA-exception` for this rule are excluded from validation

message: '{{error}} https://mdb.link/mongodb-atlas-openapi-validation#xgen-IPA-132-get-method-must-not-be-lro'
severity: warn
given: '#GetOperationObject'
then:
function: IPA132GetMethodMustNotBeLro

xgen-IPA-132-list-method-must-not-be-lro:
description: |
A List method must not be a long-running operation. A List returns data from a collection
that already exists on the server.

##### Implementation details
Rule checks for the following conditions:

- Applies to GET methods on resource collections
- The List method must not declare a 202 response; a List returns existing collection
data, so the response is returned within the request cycle
- Operations with `x-xgen-IPA-exception` for this rule are excluded from validation

message: '{{error}} https://mdb.link/mongodb-atlas-openapi-validation#xgen-IPA-132-list-method-must-not-be-lro'
severity: warn
given: '#GetOperationObject'
then:
function: IPA132ListMethodMustNotBeLro
28 changes: 28 additions & 0 deletions tools/spectral/ipa/rulesets/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1586,6 +1586,34 @@ Rule checks for the following conditions:
rule
- Schemas with `x-xgen-IPA-exception` for this rule are excluded from validation

#### xgen-IPA-132-get-method-must-not-be-lro

![warn](https://img.shields.io/badge/warning-yellow)
A Get method must not be a long-running operation. A Get returns the current state of a
single resource that already resides on the server.

##### Implementation details
Rule checks for the following conditions:

- Applies to GET methods on single resources and singleton resources
- The Get method must not declare a 202 response; a Get reads state that already exists on
the server, so there is no background work to track
- Operations with `x-xgen-IPA-exception` for this rule are excluded from validation

#### xgen-IPA-132-list-method-must-not-be-lro

![warn](https://img.shields.io/badge/warning-yellow)
A List method must not be a long-running operation. A List returns data from a collection
that already exists on the server.

##### Implementation details
Rule checks for the following conditions:

- Applies to GET methods on resource collections
- The List method must not declare a 202 response; a List returns existing collection
data, so the response is returned within the request cycle
- Operations with `x-xgen-IPA-exception` for this rule are excluded from validation




Loading
Loading