forked from snyk/vervet
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: per-operation versioning and deprecation
Fixes snyk#99, snyk#100. This changes how operation (path + method) are resolved and merged across spec versions within a stability level. Operations are now cumulative. Unless a particular operation (path + method) is redefined or explicitly deprecated, past releases are assumed to carry over to newer versions. BREAKING CHANGE: This changes the behavior of the compiler and resulting output. It's also a breaking API change, requiring a major version bump. We do not anticipate any breaking changes to OpenAPI consumers.
- Loading branch information
Showing
25 changed files
with
3,033 additions
and
251 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
package vervet | ||
|
||
import ( | ||
"fmt" | ||
"sort" | ||
|
||
"github.com/getkin/kin-openapi/openapi3" | ||
) | ||
|
||
type resourceVersionsSlice []*ResourceVersions | ||
|
||
func (s resourceVersionsSlice) validate() error { | ||
for _, v := range s.versions() { | ||
resourcePaths := map[string]string{} | ||
for _, eps := range s { | ||
ep, err := eps.At(v.String()) | ||
if err == ErrNoMatchingVersion { | ||
continue | ||
} else if err != nil { | ||
return fmt.Errorf("validation failed: %w", err) | ||
} | ||
for path := range ep.Paths { | ||
if conflict, ok := resourcePaths[path]; ok { | ||
return fmt.Errorf("conflict: %q %q", conflict, ep.sourcePrefix) | ||
} | ||
resourcePaths[path] = ep.sourcePrefix | ||
} | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
func (s resourceVersionsSlice) versions() VersionSlice { | ||
vset := map[Version]bool{} | ||
for _, eps := range s { | ||
for i := range eps.versions { | ||
vset[eps.versions[i].Version] = true | ||
} | ||
} | ||
var versions VersionSlice | ||
for v := range vset { | ||
versions = append(versions, v) | ||
} | ||
sort.Sort(versions) | ||
return versions | ||
} | ||
|
||
func (s resourceVersionsSlice) at(v Version) (*openapi3.T, error) { | ||
var result *openapi3.T | ||
for _, eps := range s { | ||
ep, err := eps.At(v.String()) | ||
if err == ErrNoMatchingVersion { | ||
continue | ||
} else if err != nil { | ||
return nil, err | ||
} | ||
if result == nil { | ||
// Assign a clean copy of the contents of the first resource to the | ||
// resulting spec. Marshaling is used to ensure that references in | ||
// the source resource are dropped from the result, which could be | ||
// modified on subsequent merges. | ||
buf, err := ep.T.MarshalJSON() | ||
if err != nil { | ||
return nil, err | ||
} | ||
result = &openapi3.T{} | ||
err = result.UnmarshalJSON(buf) | ||
if err != nil { | ||
return nil, err | ||
} | ||
} | ||
Merge(result, ep.T, false) | ||
} | ||
if result == nil { | ||
return nil, ErrNoMatchingVersion | ||
} | ||
// Remove the API stability extension from the merged OpenAPI spec, this | ||
// extension is only applicable to individual resource version specs. | ||
delete(result.ExtensionProps.Extensions, ExtSnykApiStability) | ||
return result, nil | ||
} |
Oops, something went wrong.