mirror of
https://github.com/LukeHagar/libopenapi.git
synced 2025-12-06 12:37:49 +00:00
Change indentation to tabs
This commit is contained in:
committed by
Dave Shanley
parent
d6031b5440
commit
b395518a5e
@@ -4,11 +4,12 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"reflect"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/v2"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/v3"
|
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
"reflect"
|
v2 "github.com/pb33f/libopenapi/datamodel/low/v2"
|
||||||
|
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ComponentsChanges represents changes made to both OpenAPI and Swagger documents. This model is based on OpenAPI 3
|
// ComponentsChanges represents changes made to both OpenAPI and Swagger documents. This model is based on OpenAPI 3
|
||||||
@@ -35,228 +36,228 @@ import (
|
|||||||
// modifications are not checked, these checks occur in-place by implementing objects as they are autp-resolved
|
// modifications are not checked, these checks occur in-place by implementing objects as they are autp-resolved
|
||||||
// when the model is built.
|
// when the model is built.
|
||||||
type ComponentsChanges struct {
|
type ComponentsChanges struct {
|
||||||
*PropertyChanges
|
*PropertyChanges
|
||||||
SchemaChanges map[string]*SchemaChanges `json:"schemas,omitempty" yaml:"schemas,omitempty"`
|
SchemaChanges map[string]*SchemaChanges `json:"schemas,omitempty" yaml:"schemas,omitempty"`
|
||||||
SecuritySchemeChanges map[string]*SecuritySchemeChanges `json:"securitySchemes,omitempty" yaml:"securitySchemes,omitempty"`
|
SecuritySchemeChanges map[string]*SecuritySchemeChanges `json:"securitySchemes,omitempty" yaml:"securitySchemes,omitempty"`
|
||||||
ExtensionChanges *ExtensionChanges `json:"extensions,omitempty" yaml:"extensions,omitempty"`
|
ExtensionChanges *ExtensionChanges `json:"extensions,omitempty" yaml:"extensions,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// CompareComponents will compare OpenAPI components for any changes. Accepts Swagger Definition objects
|
// CompareComponents will compare OpenAPI components for any changes. Accepts Swagger Definition objects
|
||||||
// like ParameterDefinitions or Definitions etc.
|
// like ParameterDefinitions or Definitions etc.
|
||||||
func CompareComponents(l, r any) *ComponentsChanges {
|
func CompareComponents(l, r any) *ComponentsChanges {
|
||||||
|
|
||||||
var changes []*Change
|
var changes []*Change
|
||||||
|
|
||||||
cc := new(ComponentsChanges)
|
cc := new(ComponentsChanges)
|
||||||
|
|
||||||
// Swagger Parameters
|
// Swagger Parameters
|
||||||
if reflect.TypeOf(&v2.ParameterDefinitions{}) == reflect.TypeOf(l) &&
|
if reflect.TypeOf(&v2.ParameterDefinitions{}) == reflect.TypeOf(l) &&
|
||||||
reflect.TypeOf(&v2.ParameterDefinitions{}) == reflect.TypeOf(r) {
|
reflect.TypeOf(&v2.ParameterDefinitions{}) == reflect.TypeOf(r) {
|
||||||
lDef := l.(*v2.ParameterDefinitions)
|
lDef := l.(*v2.ParameterDefinitions)
|
||||||
rDef := r.(*v2.ParameterDefinitions)
|
rDef := r.(*v2.ParameterDefinitions)
|
||||||
var a, b map[low.KeyReference[string]]low.ValueReference[*v2.Parameter]
|
var a, b map[low.KeyReference[string]]low.ValueReference[*v2.Parameter]
|
||||||
if lDef != nil {
|
if lDef != nil {
|
||||||
a = lDef.Definitions
|
a = lDef.Definitions
|
||||||
}
|
}
|
||||||
if rDef != nil {
|
if rDef != nil {
|
||||||
b = rDef.Definitions
|
b = rDef.Definitions
|
||||||
}
|
}
|
||||||
CheckMapForAdditionRemoval(a, b, &changes, v3.ParametersLabel)
|
CheckMapForAdditionRemoval(a, b, &changes, v3.ParametersLabel)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Swagger Responses
|
// Swagger Responses
|
||||||
if reflect.TypeOf(&v2.ResponsesDefinitions{}) == reflect.TypeOf(l) &&
|
if reflect.TypeOf(&v2.ResponsesDefinitions{}) == reflect.TypeOf(l) &&
|
||||||
reflect.TypeOf(&v2.ResponsesDefinitions{}) == reflect.TypeOf(r) {
|
reflect.TypeOf(&v2.ResponsesDefinitions{}) == reflect.TypeOf(r) {
|
||||||
lDef := l.(*v2.ResponsesDefinitions)
|
lDef := l.(*v2.ResponsesDefinitions)
|
||||||
rDef := r.(*v2.ResponsesDefinitions)
|
rDef := r.(*v2.ResponsesDefinitions)
|
||||||
var a, b map[low.KeyReference[string]]low.ValueReference[*v2.Response]
|
var a, b map[low.KeyReference[string]]low.ValueReference[*v2.Response]
|
||||||
if lDef != nil {
|
if lDef != nil {
|
||||||
a = lDef.Definitions
|
a = lDef.Definitions
|
||||||
}
|
}
|
||||||
if rDef != nil {
|
if rDef != nil {
|
||||||
b = rDef.Definitions
|
b = rDef.Definitions
|
||||||
}
|
}
|
||||||
CheckMapForAdditionRemoval(a, b, &changes, v3.ResponsesLabel)
|
CheckMapForAdditionRemoval(a, b, &changes, v3.ResponsesLabel)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Swagger Schemas
|
// Swagger Schemas
|
||||||
if reflect.TypeOf(&v2.Definitions{}) == reflect.TypeOf(l) &&
|
if reflect.TypeOf(&v2.Definitions{}) == reflect.TypeOf(l) &&
|
||||||
reflect.TypeOf(&v2.Definitions{}) == reflect.TypeOf(r) {
|
reflect.TypeOf(&v2.Definitions{}) == reflect.TypeOf(r) {
|
||||||
lDef := l.(*v2.Definitions)
|
lDef := l.(*v2.Definitions)
|
||||||
rDef := r.(*v2.Definitions)
|
rDef := r.(*v2.Definitions)
|
||||||
var a, b map[low.KeyReference[string]]low.ValueReference[*base.SchemaProxy]
|
var a, b map[low.KeyReference[string]]low.ValueReference[*base.SchemaProxy]
|
||||||
if lDef != nil {
|
if lDef != nil {
|
||||||
a = lDef.Schemas
|
a = lDef.Schemas
|
||||||
}
|
}
|
||||||
if rDef != nil {
|
if rDef != nil {
|
||||||
b = rDef.Schemas
|
b = rDef.Schemas
|
||||||
}
|
}
|
||||||
cc.SchemaChanges = CheckMapForChanges(a, b, &changes, v2.DefinitionsLabel, CompareSchemas)
|
cc.SchemaChanges = CheckMapForChanges(a, b, &changes, v2.DefinitionsLabel, CompareSchemas)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Swagger Security Definitions
|
// Swagger Security Definitions
|
||||||
if reflect.TypeOf(&v2.SecurityDefinitions{}) == reflect.TypeOf(l) &&
|
if reflect.TypeOf(&v2.SecurityDefinitions{}) == reflect.TypeOf(l) &&
|
||||||
reflect.TypeOf(&v2.SecurityDefinitions{}) == reflect.TypeOf(r) {
|
reflect.TypeOf(&v2.SecurityDefinitions{}) == reflect.TypeOf(r) {
|
||||||
lDef := l.(*v2.SecurityDefinitions)
|
lDef := l.(*v2.SecurityDefinitions)
|
||||||
rDef := r.(*v2.SecurityDefinitions)
|
rDef := r.(*v2.SecurityDefinitions)
|
||||||
var a, b map[low.KeyReference[string]]low.ValueReference[*v2.SecurityScheme]
|
var a, b map[low.KeyReference[string]]low.ValueReference[*v2.SecurityScheme]
|
||||||
if lDef != nil {
|
if lDef != nil {
|
||||||
a = lDef.Definitions
|
a = lDef.Definitions
|
||||||
}
|
}
|
||||||
if rDef != nil {
|
if rDef != nil {
|
||||||
b = rDef.Definitions
|
b = rDef.Definitions
|
||||||
}
|
}
|
||||||
cc.SecuritySchemeChanges = CheckMapForChanges(a, b, &changes,
|
cc.SecuritySchemeChanges = CheckMapForChanges(a, b, &changes,
|
||||||
v3.SecurityDefinitionLabel, CompareSecuritySchemesV2)
|
v3.SecurityDefinitionLabel, CompareSecuritySchemesV2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenAPI Components
|
// OpenAPI Components
|
||||||
if reflect.TypeOf(&v3.Components{}) == reflect.TypeOf(l) &&
|
if reflect.TypeOf(&v3.Components{}) == reflect.TypeOf(l) &&
|
||||||
reflect.TypeOf(&v3.Components{}) == reflect.TypeOf(r) {
|
reflect.TypeOf(&v3.Components{}) == reflect.TypeOf(r) {
|
||||||
|
|
||||||
lComponents := l.(*v3.Components)
|
lComponents := l.(*v3.Components)
|
||||||
rComponents := r.(*v3.Components)
|
rComponents := r.(*v3.Components)
|
||||||
|
|
||||||
//if low.AreEqual(lComponents, rComponents) {
|
//if low.AreEqual(lComponents, rComponents) {
|
||||||
// return nil
|
// return nil
|
||||||
//}
|
//}
|
||||||
|
|
||||||
doneChan := make(chan componentComparison)
|
doneChan := make(chan componentComparison)
|
||||||
comparisons := 0
|
comparisons := 0
|
||||||
|
|
||||||
// run as fast as we can, thread all the things.
|
// run as fast as we can, thread all the things.
|
||||||
if !lComponents.Schemas.IsEmpty() || !rComponents.Schemas.IsEmpty() {
|
if !lComponents.Schemas.IsEmpty() || !rComponents.Schemas.IsEmpty() {
|
||||||
comparisons++
|
comparisons++
|
||||||
go runComparison(lComponents.Schemas.Value, rComponents.Schemas.Value,
|
go runComparison(lComponents.Schemas.Value, rComponents.Schemas.Value,
|
||||||
&changes, v3.SchemasLabel, CompareSchemas, doneChan)
|
&changes, v3.SchemasLabel, CompareSchemas, doneChan)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !lComponents.Responses.IsEmpty() || !rComponents.Responses.IsEmpty() {
|
if !lComponents.Responses.IsEmpty() || !rComponents.Responses.IsEmpty() {
|
||||||
comparisons++
|
comparisons++
|
||||||
go runComparison(lComponents.Responses.Value, rComponents.Responses.Value,
|
go runComparison(lComponents.Responses.Value, rComponents.Responses.Value,
|
||||||
&changes, v3.ResponsesLabel, CompareResponseV3, doneChan)
|
&changes, v3.ResponsesLabel, CompareResponseV3, doneChan)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !lComponents.Parameters.IsEmpty() || !rComponents.Parameters.IsEmpty() {
|
if !lComponents.Parameters.IsEmpty() || !rComponents.Parameters.IsEmpty() {
|
||||||
comparisons++
|
comparisons++
|
||||||
go runComparison(lComponents.Parameters.Value, rComponents.Parameters.Value,
|
go runComparison(lComponents.Parameters.Value, rComponents.Parameters.Value,
|
||||||
&changes, v3.ParametersLabel, CompareParametersV3, doneChan)
|
&changes, v3.ParametersLabel, CompareParametersV3, doneChan)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !lComponents.Examples.IsEmpty() || !rComponents.Examples.IsEmpty() {
|
if !lComponents.Examples.IsEmpty() || !rComponents.Examples.IsEmpty() {
|
||||||
comparisons++
|
comparisons++
|
||||||
go runComparison(lComponents.Examples.Value, rComponents.Examples.Value,
|
go runComparison(lComponents.Examples.Value, rComponents.Examples.Value,
|
||||||
&changes, v3.ExamplesLabel, CompareExamples, doneChan)
|
&changes, v3.ExamplesLabel, CompareExamples, doneChan)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !lComponents.RequestBodies.IsEmpty() || !rComponents.RequestBodies.IsEmpty() {
|
if !lComponents.RequestBodies.IsEmpty() || !rComponents.RequestBodies.IsEmpty() {
|
||||||
comparisons++
|
comparisons++
|
||||||
go runComparison(lComponents.RequestBodies.Value, rComponents.RequestBodies.Value,
|
go runComparison(lComponents.RequestBodies.Value, rComponents.RequestBodies.Value,
|
||||||
&changes, v3.RequestBodiesLabel, CompareRequestBodies, doneChan)
|
&changes, v3.RequestBodiesLabel, CompareRequestBodies, doneChan)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !lComponents.Headers.IsEmpty() || !rComponents.Headers.IsEmpty() {
|
if !lComponents.Headers.IsEmpty() || !rComponents.Headers.IsEmpty() {
|
||||||
comparisons++
|
comparisons++
|
||||||
go runComparison(lComponents.Headers.Value, rComponents.Headers.Value,
|
go runComparison(lComponents.Headers.Value, rComponents.Headers.Value,
|
||||||
&changes, v3.HeadersLabel, CompareHeadersV3, doneChan)
|
&changes, v3.HeadersLabel, CompareHeadersV3, doneChan)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !lComponents.SecuritySchemes.IsEmpty() || !rComponents.SecuritySchemes.IsEmpty() {
|
if !lComponents.SecuritySchemes.IsEmpty() || !rComponents.SecuritySchemes.IsEmpty() {
|
||||||
comparisons++
|
comparisons++
|
||||||
go runComparison(lComponents.SecuritySchemes.Value, rComponents.SecuritySchemes.Value,
|
go runComparison(lComponents.SecuritySchemes.Value, rComponents.SecuritySchemes.Value,
|
||||||
&changes, v3.SecuritySchemesLabel, CompareSecuritySchemesV3, doneChan)
|
&changes, v3.SecuritySchemesLabel, CompareSecuritySchemesV3, doneChan)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !lComponents.Links.IsEmpty() || !rComponents.Links.IsEmpty() {
|
if !lComponents.Links.IsEmpty() || !rComponents.Links.IsEmpty() {
|
||||||
comparisons++
|
comparisons++
|
||||||
go runComparison(lComponents.Links.Value, rComponents.Links.Value,
|
go runComparison(lComponents.Links.Value, rComponents.Links.Value,
|
||||||
&changes, v3.LinksLabel, CompareLinks, doneChan)
|
&changes, v3.LinksLabel, CompareLinks, doneChan)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !lComponents.Callbacks.IsEmpty() || !rComponents.Callbacks.IsEmpty() {
|
if !lComponents.Callbacks.IsEmpty() || !rComponents.Callbacks.IsEmpty() {
|
||||||
comparisons++
|
comparisons++
|
||||||
go runComparison(lComponents.Callbacks.Value, rComponents.Callbacks.Value,
|
go runComparison(lComponents.Callbacks.Value, rComponents.Callbacks.Value,
|
||||||
&changes, v3.CallbacksLabel, CompareCallback, doneChan)
|
&changes, v3.CallbacksLabel, CompareCallback, doneChan)
|
||||||
}
|
}
|
||||||
|
|
||||||
cc.ExtensionChanges = CompareExtensions(lComponents.Extensions, rComponents.Extensions)
|
cc.ExtensionChanges = CompareExtensions(lComponents.Extensions, rComponents.Extensions)
|
||||||
|
|
||||||
completedComponents := 0
|
completedComponents := 0
|
||||||
for completedComponents < comparisons {
|
for completedComponents < comparisons {
|
||||||
select {
|
select {
|
||||||
case res := <-doneChan:
|
case res := <-doneChan:
|
||||||
switch res.prop {
|
switch res.prop {
|
||||||
case v3.SchemasLabel:
|
case v3.SchemasLabel:
|
||||||
completedComponents++
|
completedComponents++
|
||||||
cc.SchemaChanges = res.result.(map[string]*SchemaChanges)
|
cc.SchemaChanges = res.result.(map[string]*SchemaChanges)
|
||||||
break
|
break
|
||||||
case v3.SecuritySchemesLabel:
|
case v3.SecuritySchemesLabel:
|
||||||
completedComponents++
|
completedComponents++
|
||||||
cc.SecuritySchemeChanges = res.result.(map[string]*SecuritySchemeChanges)
|
cc.SecuritySchemeChanges = res.result.(map[string]*SecuritySchemeChanges)
|
||||||
break
|
break
|
||||||
case v3.ResponsesLabel, v3.ParametersLabel, v3.ExamplesLabel, v3.RequestBodiesLabel, v3.HeadersLabel,
|
case v3.ResponsesLabel, v3.ParametersLabel, v3.ExamplesLabel, v3.RequestBodiesLabel, v3.HeadersLabel,
|
||||||
v3.LinksLabel, v3.CallbacksLabel:
|
v3.LinksLabel, v3.CallbacksLabel:
|
||||||
completedComponents++
|
completedComponents++
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cc.PropertyChanges = NewPropertyChanges(changes)
|
cc.PropertyChanges = NewPropertyChanges(changes)
|
||||||
if cc.TotalChanges() <= 0 {
|
if cc.TotalChanges() <= 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return cc
|
return cc
|
||||||
}
|
}
|
||||||
|
|
||||||
type componentComparison struct {
|
type componentComparison struct {
|
||||||
prop string
|
prop string
|
||||||
result any
|
result any
|
||||||
}
|
}
|
||||||
|
|
||||||
// run a generic comparison in a thread which in turn splits checks into further threads.
|
// run a generic comparison in a thread which in turn splits checks into further threads.
|
||||||
func runComparison[T any, R any](l, r map[low.KeyReference[string]]low.ValueReference[T],
|
func runComparison[T any, R any](l, r map[low.KeyReference[string]]low.ValueReference[T],
|
||||||
changes *[]*Change, label string, compareFunc func(l, r T) R, doneChan chan componentComparison) {
|
changes *[]*Change, label string, compareFunc func(l, r T) R, doneChan chan componentComparison) {
|
||||||
|
|
||||||
// for schemas
|
// for schemas
|
||||||
if label == v3.SchemasLabel || label == v2.DefinitionsLabel || label == v3.SecuritySchemesLabel {
|
if label == v3.SchemasLabel || label == v2.DefinitionsLabel || label == v3.SecuritySchemesLabel {
|
||||||
doneChan <- componentComparison{
|
doneChan <- componentComparison{
|
||||||
prop: label,
|
prop: label,
|
||||||
result: CheckMapForChanges(l, r, changes, label, compareFunc),
|
result: CheckMapForChanges(l, r, changes, label, compareFunc),
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
doneChan <- componentComparison{
|
doneChan <- componentComparison{
|
||||||
prop: label,
|
prop: label,
|
||||||
result: CheckMapForAdditionRemoval(l, r, changes, label),
|
result: CheckMapForAdditionRemoval(l, r, changes, label),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TotalChanges returns total changes for all Components and Definitions
|
// TotalChanges returns total changes for all Components and Definitions
|
||||||
func (c *ComponentsChanges) TotalChanges() int {
|
func (c *ComponentsChanges) TotalChanges() int {
|
||||||
v := c.PropertyChanges.TotalChanges()
|
v := c.PropertyChanges.TotalChanges()
|
||||||
for k := range c.SchemaChanges {
|
for k := range c.SchemaChanges {
|
||||||
v += c.SchemaChanges[k].TotalChanges()
|
v += c.SchemaChanges[k].TotalChanges()
|
||||||
}
|
}
|
||||||
for k := range c.SecuritySchemeChanges {
|
for k := range c.SecuritySchemeChanges {
|
||||||
v += c.SecuritySchemeChanges[k].TotalChanges()
|
v += c.SecuritySchemeChanges[k].TotalChanges()
|
||||||
}
|
}
|
||||||
if c.ExtensionChanges != nil {
|
if c.ExtensionChanges != nil {
|
||||||
v += c.ExtensionChanges.TotalChanges()
|
v += c.ExtensionChanges.TotalChanges()
|
||||||
}
|
}
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// TotalBreakingChanges returns all breaking changes found for all Components and Definitions
|
// TotalBreakingChanges returns all breaking changes found for all Components and Definitions
|
||||||
func (c *ComponentsChanges) TotalBreakingChanges() int {
|
func (c *ComponentsChanges) TotalBreakingChanges() int {
|
||||||
v := c.PropertyChanges.TotalBreakingChanges()
|
v := c.PropertyChanges.TotalBreakingChanges()
|
||||||
for k := range c.SchemaChanges {
|
for k := range c.SchemaChanges {
|
||||||
v += c.SchemaChanges[k].TotalBreakingChanges()
|
v += c.SchemaChanges[k].TotalBreakingChanges()
|
||||||
}
|
}
|
||||||
for k := range c.SecuritySchemeChanges {
|
for k := range c.SecuritySchemeChanges {
|
||||||
v += c.SecuritySchemeChanges[k].TotalBreakingChanges()
|
v += c.SecuritySchemeChanges[k].TotalBreakingChanges()
|
||||||
}
|
}
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,279 +11,280 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"reflect"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/v2"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/v3"
|
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
"reflect"
|
v2 "github.com/pb33f/libopenapi/datamodel/low/v2"
|
||||||
|
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DocumentChanges represents all the changes made to an OpenAPI document.
|
// DocumentChanges represents all the changes made to an OpenAPI document.
|
||||||
type DocumentChanges struct {
|
type DocumentChanges struct {
|
||||||
*PropertyChanges
|
*PropertyChanges
|
||||||
InfoChanges *InfoChanges `json:"info,omitempty" yaml:"info,omitempty"`
|
InfoChanges *InfoChanges `json:"info,omitempty" yaml:"info,omitempty"`
|
||||||
PathsChanges *PathsChanges `json:"paths,omitempty" yaml:"paths,omitempty"`
|
PathsChanges *PathsChanges `json:"paths,omitempty" yaml:"paths,omitempty"`
|
||||||
TagChanges []*TagChanges `json:"tags,omitempty" yaml:"tags,omitempty"`
|
TagChanges []*TagChanges `json:"tags,omitempty" yaml:"tags,omitempty"`
|
||||||
ExternalDocChanges *ExternalDocChanges `json:"externalDoc,omitempty" yaml:"externalDoc,omitempty"`
|
ExternalDocChanges *ExternalDocChanges `json:"externalDoc,omitempty" yaml:"externalDoc,omitempty"`
|
||||||
WebhookChanges map[string]*PathItemChanges `json:"webhooks,omitempty" yaml:"webhooks,omitempty"`
|
WebhookChanges map[string]*PathItemChanges `json:"webhooks,omitempty" yaml:"webhooks,omitempty"`
|
||||||
ServerChanges []*ServerChanges `json:"servers,omitempty" yaml:"servers,omitempty"`
|
ServerChanges []*ServerChanges `json:"servers,omitempty" yaml:"servers,omitempty"`
|
||||||
SecurityRequirementChanges []*SecurityRequirementChanges `json:"securityRequirements,omitempty" yaml:"securityRequirements,omitempty"`
|
SecurityRequirementChanges []*SecurityRequirementChanges `json:"securityRequirements,omitempty" yaml:"securityRequirements,omitempty"`
|
||||||
ComponentsChanges *ComponentsChanges `json:"components,omitempty" yaml:"components,omitempty"`
|
ComponentsChanges *ComponentsChanges `json:"components,omitempty" yaml:"components,omitempty"`
|
||||||
ExtensionChanges *ExtensionChanges `json:"extensions,omitempty" yaml:"extensions,omitempty"`
|
ExtensionChanges *ExtensionChanges `json:"extensions,omitempty" yaml:"extensions,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// TotalChanges returns a total count of all changes made in the Document
|
// TotalChanges returns a total count of all changes made in the Document
|
||||||
func (d *DocumentChanges) TotalChanges() int {
|
func (d *DocumentChanges) TotalChanges() int {
|
||||||
c := d.PropertyChanges.TotalChanges()
|
c := d.PropertyChanges.TotalChanges()
|
||||||
if d.InfoChanges != nil {
|
if d.InfoChanges != nil {
|
||||||
c += d.InfoChanges.TotalChanges()
|
c += d.InfoChanges.TotalChanges()
|
||||||
}
|
}
|
||||||
if d.PathsChanges != nil {
|
if d.PathsChanges != nil {
|
||||||
c += d.PathsChanges.TotalChanges()
|
c += d.PathsChanges.TotalChanges()
|
||||||
}
|
}
|
||||||
for k := range d.TagChanges {
|
for k := range d.TagChanges {
|
||||||
c += d.TagChanges[k].TotalChanges()
|
c += d.TagChanges[k].TotalChanges()
|
||||||
}
|
}
|
||||||
if d.ExternalDocChanges != nil {
|
if d.ExternalDocChanges != nil {
|
||||||
c += d.ExternalDocChanges.TotalChanges()
|
c += d.ExternalDocChanges.TotalChanges()
|
||||||
}
|
}
|
||||||
for k := range d.WebhookChanges {
|
for k := range d.WebhookChanges {
|
||||||
c += d.WebhookChanges[k].TotalChanges()
|
c += d.WebhookChanges[k].TotalChanges()
|
||||||
}
|
}
|
||||||
for k := range d.ServerChanges {
|
for k := range d.ServerChanges {
|
||||||
c += d.ServerChanges[k].TotalChanges()
|
c += d.ServerChanges[k].TotalChanges()
|
||||||
}
|
}
|
||||||
for k := range d.SecurityRequirementChanges {
|
for k := range d.SecurityRequirementChanges {
|
||||||
c += d.SecurityRequirementChanges[k].TotalChanges()
|
c += d.SecurityRequirementChanges[k].TotalChanges()
|
||||||
}
|
}
|
||||||
if d.ComponentsChanges != nil {
|
if d.ComponentsChanges != nil {
|
||||||
c += d.ComponentsChanges.TotalChanges()
|
c += d.ComponentsChanges.TotalChanges()
|
||||||
}
|
}
|
||||||
if d.ExtensionChanges != nil {
|
if d.ExtensionChanges != nil {
|
||||||
c += d.ExtensionChanges.TotalChanges()
|
c += d.ExtensionChanges.TotalChanges()
|
||||||
}
|
}
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// TotalBreakingChanges returns a total count of all breaking changes made in the Document
|
// TotalBreakingChanges returns a total count of all breaking changes made in the Document
|
||||||
func (d *DocumentChanges) TotalBreakingChanges() int {
|
func (d *DocumentChanges) TotalBreakingChanges() int {
|
||||||
c := d.PropertyChanges.TotalBreakingChanges()
|
c := d.PropertyChanges.TotalBreakingChanges()
|
||||||
if d.InfoChanges != nil {
|
if d.InfoChanges != nil {
|
||||||
c += d.InfoChanges.TotalBreakingChanges()
|
c += d.InfoChanges.TotalBreakingChanges()
|
||||||
}
|
}
|
||||||
if d.PathsChanges != nil {
|
if d.PathsChanges != nil {
|
||||||
c += d.PathsChanges.TotalBreakingChanges()
|
c += d.PathsChanges.TotalBreakingChanges()
|
||||||
}
|
}
|
||||||
for k := range d.TagChanges {
|
for k := range d.TagChanges {
|
||||||
c += d.TagChanges[k].TotalBreakingChanges()
|
c += d.TagChanges[k].TotalBreakingChanges()
|
||||||
}
|
}
|
||||||
if d.ExternalDocChanges != nil {
|
if d.ExternalDocChanges != nil {
|
||||||
c += d.ExternalDocChanges.TotalBreakingChanges()
|
c += d.ExternalDocChanges.TotalBreakingChanges()
|
||||||
}
|
}
|
||||||
for k := range d.WebhookChanges {
|
for k := range d.WebhookChanges {
|
||||||
c += d.WebhookChanges[k].TotalBreakingChanges()
|
c += d.WebhookChanges[k].TotalBreakingChanges()
|
||||||
}
|
}
|
||||||
for k := range d.ServerChanges {
|
for k := range d.ServerChanges {
|
||||||
c += d.ServerChanges[k].TotalBreakingChanges()
|
c += d.ServerChanges[k].TotalBreakingChanges()
|
||||||
}
|
}
|
||||||
for k := range d.SecurityRequirementChanges {
|
for k := range d.SecurityRequirementChanges {
|
||||||
c += d.SecurityRequirementChanges[k].TotalBreakingChanges()
|
c += d.SecurityRequirementChanges[k].TotalBreakingChanges()
|
||||||
}
|
}
|
||||||
if d.ComponentsChanges != nil {
|
if d.ComponentsChanges != nil {
|
||||||
c += d.ComponentsChanges.TotalBreakingChanges()
|
c += d.ComponentsChanges.TotalBreakingChanges()
|
||||||
}
|
}
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// CompareDocuments will compare any two OpenAPI documents (either Swagger or OpenAPI) and return a pointer to
|
// CompareDocuments will compare any two OpenAPI documents (either Swagger or OpenAPI) and return a pointer to
|
||||||
// DocumentChanges that outlines everything that was found to have changed.
|
// DocumentChanges that outlines everything that was found to have changed.
|
||||||
func CompareDocuments(l, r any) *DocumentChanges {
|
func CompareDocuments(l, r any) *DocumentChanges {
|
||||||
|
|
||||||
var changes []*Change
|
var changes []*Change
|
||||||
var props []*PropertyCheck
|
var props []*PropertyCheck
|
||||||
|
|
||||||
dc := new(DocumentChanges)
|
dc := new(DocumentChanges)
|
||||||
|
|
||||||
if reflect.TypeOf(&v2.Swagger{}) == reflect.TypeOf(l) && reflect.TypeOf(&v2.Swagger{}) == reflect.TypeOf(r) {
|
if reflect.TypeOf(&v2.Swagger{}) == reflect.TypeOf(l) && reflect.TypeOf(&v2.Swagger{}) == reflect.TypeOf(r) {
|
||||||
lDoc := l.(*v2.Swagger)
|
lDoc := l.(*v2.Swagger)
|
||||||
rDoc := r.(*v2.Swagger)
|
rDoc := r.(*v2.Swagger)
|
||||||
|
|
||||||
// version
|
// version
|
||||||
addPropertyCheck(&props, lDoc.Swagger.ValueNode, rDoc.Swagger.ValueNode,
|
addPropertyCheck(&props, lDoc.Swagger.ValueNode, rDoc.Swagger.ValueNode,
|
||||||
lDoc.Swagger.Value, rDoc.Swagger.Value, &changes, v3.SwaggerLabel, true)
|
lDoc.Swagger.Value, rDoc.Swagger.Value, &changes, v3.SwaggerLabel, true)
|
||||||
|
|
||||||
// host
|
// host
|
||||||
addPropertyCheck(&props, lDoc.Host.ValueNode, rDoc.Host.ValueNode,
|
addPropertyCheck(&props, lDoc.Host.ValueNode, rDoc.Host.ValueNode,
|
||||||
lDoc.Host.Value, rDoc.Host.Value, &changes, v3.HostLabel, true)
|
lDoc.Host.Value, rDoc.Host.Value, &changes, v3.HostLabel, true)
|
||||||
|
|
||||||
// base path
|
// base path
|
||||||
addPropertyCheck(&props, lDoc.BasePath.ValueNode, rDoc.BasePath.ValueNode,
|
addPropertyCheck(&props, lDoc.BasePath.ValueNode, rDoc.BasePath.ValueNode,
|
||||||
lDoc.BasePath.Value, rDoc.BasePath.Value, &changes, v3.BasePathLabel, true)
|
lDoc.BasePath.Value, rDoc.BasePath.Value, &changes, v3.BasePathLabel, true)
|
||||||
|
|
||||||
// schemes
|
// schemes
|
||||||
if len(lDoc.Schemes.Value) > 0 || len(lDoc.Schemes.Value) > 0 {
|
if len(lDoc.Schemes.Value) > 0 || len(lDoc.Schemes.Value) > 0 {
|
||||||
ExtractStringValueSliceChanges(lDoc.Schemes.Value, rDoc.Schemes.Value,
|
ExtractStringValueSliceChanges(lDoc.Schemes.Value, rDoc.Schemes.Value,
|
||||||
&changes, v3.SchemesLabel, true)
|
&changes, v3.SchemesLabel, true)
|
||||||
}
|
}
|
||||||
// consumes
|
// consumes
|
||||||
if len(lDoc.Consumes.Value) > 0 || len(lDoc.Consumes.Value) > 0 {
|
if len(lDoc.Consumes.Value) > 0 || len(lDoc.Consumes.Value) > 0 {
|
||||||
ExtractStringValueSliceChanges(lDoc.Consumes.Value, rDoc.Consumes.Value,
|
ExtractStringValueSliceChanges(lDoc.Consumes.Value, rDoc.Consumes.Value,
|
||||||
&changes, v3.ConsumesLabel, true)
|
&changes, v3.ConsumesLabel, true)
|
||||||
}
|
}
|
||||||
// produces
|
// produces
|
||||||
if len(lDoc.Produces.Value) > 0 || len(lDoc.Produces.Value) > 0 {
|
if len(lDoc.Produces.Value) > 0 || len(lDoc.Produces.Value) > 0 {
|
||||||
ExtractStringValueSliceChanges(lDoc.Produces.Value, rDoc.Produces.Value,
|
ExtractStringValueSliceChanges(lDoc.Produces.Value, rDoc.Produces.Value,
|
||||||
&changes, v3.ProducesLabel, true)
|
&changes, v3.ProducesLabel, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// tags
|
// tags
|
||||||
dc.TagChanges = CompareTags(lDoc.Tags.Value, rDoc.Tags.Value)
|
dc.TagChanges = CompareTags(lDoc.Tags.Value, rDoc.Tags.Value)
|
||||||
|
|
||||||
// paths
|
// paths
|
||||||
if !lDoc.Paths.IsEmpty() || !rDoc.Paths.IsEmpty() {
|
if !lDoc.Paths.IsEmpty() || !rDoc.Paths.IsEmpty() {
|
||||||
dc.PathsChanges = ComparePaths(lDoc.Paths.Value, rDoc.Paths.Value)
|
dc.PathsChanges = ComparePaths(lDoc.Paths.Value, rDoc.Paths.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// external docs
|
// external docs
|
||||||
compareDocumentExternalDocs(lDoc, rDoc, dc, &changes)
|
compareDocumentExternalDocs(lDoc, rDoc, dc, &changes)
|
||||||
|
|
||||||
// info
|
// info
|
||||||
compareDocumentInfo(&lDoc.Info, &rDoc.Info, dc, &changes)
|
compareDocumentInfo(&lDoc.Info, &rDoc.Info, dc, &changes)
|
||||||
|
|
||||||
// security
|
// security
|
||||||
if !lDoc.Security.IsEmpty() || !rDoc.Security.IsEmpty() {
|
if !lDoc.Security.IsEmpty() || !rDoc.Security.IsEmpty() {
|
||||||
checkSecurity(lDoc.Security, rDoc.Security, &changes, dc)
|
checkSecurity(lDoc.Security, rDoc.Security, &changes, dc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// components / definitions
|
// components / definitions
|
||||||
// swagger (damn you) decided to put all this stuff at the document root, rather than cleanly
|
// swagger (damn you) decided to put all this stuff at the document root, rather than cleanly
|
||||||
// placing it under a parent, like they did with OpenAPI. This means picking through each definition
|
// placing it under a parent, like they did with OpenAPI. This means picking through each definition
|
||||||
// creating a new set of changes and then morphing them into a single changes object.
|
// creating a new set of changes and then morphing them into a single changes object.
|
||||||
cc := new(ComponentsChanges)
|
cc := new(ComponentsChanges)
|
||||||
cc.PropertyChanges = new(PropertyChanges)
|
cc.PropertyChanges = new(PropertyChanges)
|
||||||
if n := CompareComponents(lDoc.Definitions.Value, rDoc.Definitions.Value); n != nil {
|
if n := CompareComponents(lDoc.Definitions.Value, rDoc.Definitions.Value); n != nil {
|
||||||
cc.SchemaChanges = n.SchemaChanges
|
cc.SchemaChanges = n.SchemaChanges
|
||||||
}
|
}
|
||||||
if n := CompareComponents(lDoc.SecurityDefinitions.Value, rDoc.SecurityDefinitions.Value); n != nil {
|
if n := CompareComponents(lDoc.SecurityDefinitions.Value, rDoc.SecurityDefinitions.Value); n != nil {
|
||||||
cc.SecuritySchemeChanges = n.SecuritySchemeChanges
|
cc.SecuritySchemeChanges = n.SecuritySchemeChanges
|
||||||
}
|
}
|
||||||
if n := CompareComponents(lDoc.Parameters.Value, rDoc.Parameters.Value); n != nil {
|
if n := CompareComponents(lDoc.Parameters.Value, rDoc.Parameters.Value); n != nil {
|
||||||
cc.PropertyChanges.Changes = append(cc.PropertyChanges.Changes, n.Changes...)
|
cc.PropertyChanges.Changes = append(cc.PropertyChanges.Changes, n.Changes...)
|
||||||
}
|
}
|
||||||
if n := CompareComponents(lDoc.Responses.Value, rDoc.Responses.Value); n != nil {
|
if n := CompareComponents(lDoc.Responses.Value, rDoc.Responses.Value); n != nil {
|
||||||
cc.Changes = append(cc.Changes, n.Changes...)
|
cc.Changes = append(cc.Changes, n.Changes...)
|
||||||
}
|
}
|
||||||
dc.ExtensionChanges = CompareExtensions(lDoc.Extensions, rDoc.Extensions)
|
dc.ExtensionChanges = CompareExtensions(lDoc.Extensions, rDoc.Extensions)
|
||||||
if cc.TotalChanges() > 0 {
|
if cc.TotalChanges() > 0 {
|
||||||
dc.ComponentsChanges = cc
|
dc.ComponentsChanges = cc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if reflect.TypeOf(&v3.Document{}) == reflect.TypeOf(l) && reflect.TypeOf(&v3.Document{}) == reflect.TypeOf(r) {
|
if reflect.TypeOf(&v3.Document{}) == reflect.TypeOf(l) && reflect.TypeOf(&v3.Document{}) == reflect.TypeOf(r) {
|
||||||
lDoc := l.(*v3.Document)
|
lDoc := l.(*v3.Document)
|
||||||
rDoc := r.(*v3.Document)
|
rDoc := r.(*v3.Document)
|
||||||
|
|
||||||
// version
|
// version
|
||||||
addPropertyCheck(&props, lDoc.Version.ValueNode, rDoc.Version.ValueNode,
|
addPropertyCheck(&props, lDoc.Version.ValueNode, rDoc.Version.ValueNode,
|
||||||
lDoc.Version.Value, rDoc.Version.Value, &changes, v3.OpenAPILabel, true)
|
lDoc.Version.Value, rDoc.Version.Value, &changes, v3.OpenAPILabel, true)
|
||||||
|
|
||||||
// schema dialect
|
// schema dialect
|
||||||
addPropertyCheck(&props, lDoc.JsonSchemaDialect.ValueNode, rDoc.JsonSchemaDialect.ValueNode,
|
addPropertyCheck(&props, lDoc.JsonSchemaDialect.ValueNode, rDoc.JsonSchemaDialect.ValueNode,
|
||||||
lDoc.JsonSchemaDialect.Value, rDoc.JsonSchemaDialect.Value, &changes, v3.JSONSchemaDialectLabel, true)
|
lDoc.JsonSchemaDialect.Value, rDoc.JsonSchemaDialect.Value, &changes, v3.JSONSchemaDialectLabel, true)
|
||||||
|
|
||||||
// tags
|
// tags
|
||||||
dc.TagChanges = CompareTags(lDoc.Tags.Value, rDoc.Tags.Value)
|
dc.TagChanges = CompareTags(lDoc.Tags.Value, rDoc.Tags.Value)
|
||||||
|
|
||||||
// paths
|
// paths
|
||||||
if !lDoc.Paths.IsEmpty() || !rDoc.Paths.IsEmpty() {
|
if !lDoc.Paths.IsEmpty() || !rDoc.Paths.IsEmpty() {
|
||||||
dc.PathsChanges = ComparePaths(lDoc.Paths.Value, rDoc.Paths.Value)
|
dc.PathsChanges = ComparePaths(lDoc.Paths.Value, rDoc.Paths.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// external docs
|
// external docs
|
||||||
compareDocumentExternalDocs(lDoc, rDoc, dc, &changes)
|
compareDocumentExternalDocs(lDoc, rDoc, dc, &changes)
|
||||||
|
|
||||||
// info
|
// info
|
||||||
compareDocumentInfo(&lDoc.Info, &rDoc.Info, dc, &changes)
|
compareDocumentInfo(&lDoc.Info, &rDoc.Info, dc, &changes)
|
||||||
|
|
||||||
// security
|
// security
|
||||||
if !lDoc.Security.IsEmpty() || !rDoc.Security.IsEmpty() {
|
if !lDoc.Security.IsEmpty() || !rDoc.Security.IsEmpty() {
|
||||||
checkSecurity(lDoc.Security, rDoc.Security, &changes, dc)
|
checkSecurity(lDoc.Security, rDoc.Security, &changes, dc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// compare components.
|
// compare components.
|
||||||
if !lDoc.Components.IsEmpty() && !rDoc.Components.IsEmpty() {
|
if !lDoc.Components.IsEmpty() && !rDoc.Components.IsEmpty() {
|
||||||
if n := CompareComponents(lDoc.Components.Value, rDoc.Components.Value); n != nil {
|
if n := CompareComponents(lDoc.Components.Value, rDoc.Components.Value); n != nil {
|
||||||
dc.ComponentsChanges = n
|
dc.ComponentsChanges = n
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !lDoc.Components.IsEmpty() && rDoc.Components.IsEmpty() {
|
if !lDoc.Components.IsEmpty() && rDoc.Components.IsEmpty() {
|
||||||
CreateChange(&changes, PropertyRemoved, v3.ComponentsLabel,
|
CreateChange(&changes, PropertyRemoved, v3.ComponentsLabel,
|
||||||
lDoc.Components.ValueNode, nil, true, lDoc.Components.Value, nil)
|
lDoc.Components.ValueNode, nil, true, lDoc.Components.Value, nil)
|
||||||
}
|
}
|
||||||
if lDoc.Components.IsEmpty() && !rDoc.Components.IsEmpty() {
|
if lDoc.Components.IsEmpty() && !rDoc.Components.IsEmpty() {
|
||||||
CreateChange(&changes, PropertyAdded, v3.ComponentsLabel,
|
CreateChange(&changes, PropertyAdded, v3.ComponentsLabel,
|
||||||
rDoc.Components.ValueNode, nil, false, nil, lDoc.Components.Value)
|
rDoc.Components.ValueNode, nil, false, nil, lDoc.Components.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// compare servers
|
// compare servers
|
||||||
if n := checkServers(lDoc.Servers, rDoc.Servers); n != nil {
|
if n := checkServers(lDoc.Servers, rDoc.Servers); n != nil {
|
||||||
dc.ServerChanges = n
|
dc.ServerChanges = n
|
||||||
}
|
}
|
||||||
|
|
||||||
// compare webhooks
|
// compare webhooks
|
||||||
dc.WebhookChanges = CheckMapForChanges(lDoc.Webhooks.Value, rDoc.Webhooks.Value, &changes,
|
dc.WebhookChanges = CheckMapForChanges(lDoc.Webhooks.Value, rDoc.Webhooks.Value, &changes,
|
||||||
v3.WebhooksLabel, ComparePathItemsV3)
|
v3.WebhooksLabel, ComparePathItemsV3)
|
||||||
|
|
||||||
// extensions
|
// extensions
|
||||||
dc.ExtensionChanges = CompareExtensions(lDoc.Extensions, rDoc.Extensions)
|
dc.ExtensionChanges = CompareExtensions(lDoc.Extensions, rDoc.Extensions)
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckProperties(props)
|
CheckProperties(props)
|
||||||
dc.PropertyChanges = NewPropertyChanges(changes)
|
dc.PropertyChanges = NewPropertyChanges(changes)
|
||||||
if dc.TotalChanges() <= 0 {
|
if dc.TotalChanges() <= 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return dc
|
return dc
|
||||||
}
|
}
|
||||||
|
|
||||||
func compareDocumentExternalDocs(l, r low.HasExternalDocs, dc *DocumentChanges, changes *[]*Change) {
|
func compareDocumentExternalDocs(l, r low.HasExternalDocs, dc *DocumentChanges, changes *[]*Change) {
|
||||||
// external docs
|
// external docs
|
||||||
if !l.GetExternalDocs().IsEmpty() && !r.GetExternalDocs().IsEmpty() {
|
if !l.GetExternalDocs().IsEmpty() && !r.GetExternalDocs().IsEmpty() {
|
||||||
lExtDoc := l.GetExternalDocs().Value.(*base.ExternalDoc)
|
lExtDoc := l.GetExternalDocs().Value.(*base.ExternalDoc)
|
||||||
rExtDoc := r.GetExternalDocs().Value.(*base.ExternalDoc)
|
rExtDoc := r.GetExternalDocs().Value.(*base.ExternalDoc)
|
||||||
if !low.AreEqual(lExtDoc, rExtDoc) {
|
if !low.AreEqual(lExtDoc, rExtDoc) {
|
||||||
dc.ExternalDocChanges = CompareExternalDocs(lExtDoc, rExtDoc)
|
dc.ExternalDocChanges = CompareExternalDocs(lExtDoc, rExtDoc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if l.GetExternalDocs().IsEmpty() && !r.GetExternalDocs().IsEmpty() {
|
if l.GetExternalDocs().IsEmpty() && !r.GetExternalDocs().IsEmpty() {
|
||||||
CreateChange(changes, PropertyAdded, v3.ExternalDocsLabel,
|
CreateChange(changes, PropertyAdded, v3.ExternalDocsLabel,
|
||||||
nil, r.GetExternalDocs().ValueNode, false, nil,
|
nil, r.GetExternalDocs().ValueNode, false, nil,
|
||||||
r.GetExternalDocs().Value)
|
r.GetExternalDocs().Value)
|
||||||
}
|
}
|
||||||
if !l.GetExternalDocs().IsEmpty() && r.GetExternalDocs().IsEmpty() {
|
if !l.GetExternalDocs().IsEmpty() && r.GetExternalDocs().IsEmpty() {
|
||||||
CreateChange(changes, PropertyRemoved, v3.ExternalDocsLabel,
|
CreateChange(changes, PropertyRemoved, v3.ExternalDocsLabel,
|
||||||
l.GetExternalDocs().ValueNode, nil, false, l.GetExternalDocs().Value,
|
l.GetExternalDocs().ValueNode, nil, false, l.GetExternalDocs().Value,
|
||||||
nil)
|
nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func compareDocumentInfo(l, r *low.NodeReference[*base.Info], dc *DocumentChanges, changes *[]*Change) {
|
func compareDocumentInfo(l, r *low.NodeReference[*base.Info], dc *DocumentChanges, changes *[]*Change) {
|
||||||
// info
|
// info
|
||||||
if !l.IsEmpty() && !r.IsEmpty() {
|
if !l.IsEmpty() && !r.IsEmpty() {
|
||||||
lInfo := l.Value
|
lInfo := l.Value
|
||||||
rInfo := r.Value
|
rInfo := r.Value
|
||||||
if !low.AreEqual(lInfo, rInfo) {
|
if !low.AreEqual(lInfo, rInfo) {
|
||||||
dc.InfoChanges = CompareInfo(lInfo, rInfo)
|
dc.InfoChanges = CompareInfo(lInfo, rInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if l.IsEmpty() && !r.IsEmpty() {
|
if l.IsEmpty() && !r.IsEmpty() {
|
||||||
CreateChange(changes, PropertyAdded, v3.InfoLabel,
|
CreateChange(changes, PropertyAdded, v3.InfoLabel,
|
||||||
nil, r.ValueNode, false, nil,
|
nil, r.ValueNode, false, nil,
|
||||||
r.Value)
|
r.Value)
|
||||||
}
|
}
|
||||||
if !l.IsEmpty() && r.IsEmpty() {
|
if !l.IsEmpty() && r.IsEmpty() {
|
||||||
CreateChange(changes, PropertyRemoved, v3.InfoLabel,
|
CreateChange(changes, PropertyRemoved, v3.InfoLabel,
|
||||||
l.ValueNode, nil, false, l.Value,
|
l.ValueNode, nil, false, l.Value,
|
||||||
nil)
|
nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,154 +4,155 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"reflect"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
"sort"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/v2"
|
"strings"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/v3"
|
|
||||||
"gopkg.in/yaml.v3"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"reflect"
|
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
"sort"
|
v2 "github.com/pb33f/libopenapi/datamodel/low/v2"
|
||||||
"strings"
|
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// OperationChanges represent changes made between two Swagger or OpenAPI Operation objects.
|
// OperationChanges represent changes made between two Swagger or OpenAPI Operation objects.
|
||||||
type OperationChanges struct {
|
type OperationChanges struct {
|
||||||
*PropertyChanges
|
*PropertyChanges
|
||||||
ExternalDocChanges *ExternalDocChanges `json:"externalDoc,omitempty" yaml:"externalDoc,omitempty"`
|
ExternalDocChanges *ExternalDocChanges `json:"externalDoc,omitempty" yaml:"externalDoc,omitempty"`
|
||||||
ParameterChanges []*ParameterChanges `json:"parameters,omitempty" yaml:"parameters,omitempty"`
|
ParameterChanges []*ParameterChanges `json:"parameters,omitempty" yaml:"parameters,omitempty"`
|
||||||
ResponsesChanges *ResponsesChanges `json:"responses,omitempty" yaml:"responses,omitempty"`
|
ResponsesChanges *ResponsesChanges `json:"responses,omitempty" yaml:"responses,omitempty"`
|
||||||
SecurityRequirementChanges []*SecurityRequirementChanges `json:"securityRequirements,omitempty" yaml:"securityRequirements,omitempty"`
|
SecurityRequirementChanges []*SecurityRequirementChanges `json:"securityRequirements,omitempty" yaml:"securityRequirements,omitempty"`
|
||||||
|
|
||||||
// OpenAPI 3+ only changes
|
// OpenAPI 3+ only changes
|
||||||
RequestBodyChanges *RequestBodyChanges `json:"requestBodies,omitempty" yaml:"requestBodies,omitempty"`
|
RequestBodyChanges *RequestBodyChanges `json:"requestBodies,omitempty" yaml:"requestBodies,omitempty"`
|
||||||
ServerChanges []*ServerChanges `json:"servers,omitempty" yaml:"servers,omitempty"`
|
ServerChanges []*ServerChanges `json:"servers,omitempty" yaml:"servers,omitempty"`
|
||||||
ExtensionChanges *ExtensionChanges `json:"extensions,omitempty" yaml:"extensions,omitempty"`
|
ExtensionChanges *ExtensionChanges `json:"extensions,omitempty" yaml:"extensions,omitempty"`
|
||||||
CallbackChanges map[string]*CallbackChanges `json:"callbacks,omitempty" yaml:"callbacks,omitempty"`
|
CallbackChanges map[string]*CallbackChanges `json:"callbacks,omitempty" yaml:"callbacks,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// TotalChanges returns the total number of changes made between two Swagger or OpenAPI Operation objects.
|
// TotalChanges returns the total number of changes made between two Swagger or OpenAPI Operation objects.
|
||||||
func (o *OperationChanges) TotalChanges() int {
|
func (o *OperationChanges) TotalChanges() int {
|
||||||
c := o.PropertyChanges.TotalChanges()
|
c := o.PropertyChanges.TotalChanges()
|
||||||
if o.ExternalDocChanges != nil {
|
if o.ExternalDocChanges != nil {
|
||||||
c += o.ExternalDocChanges.TotalChanges()
|
c += o.ExternalDocChanges.TotalChanges()
|
||||||
}
|
}
|
||||||
for k := range o.ParameterChanges {
|
for k := range o.ParameterChanges {
|
||||||
c += o.ParameterChanges[k].TotalChanges()
|
c += o.ParameterChanges[k].TotalChanges()
|
||||||
}
|
}
|
||||||
if o.ResponsesChanges != nil {
|
if o.ResponsesChanges != nil {
|
||||||
c += o.ResponsesChanges.TotalChanges()
|
c += o.ResponsesChanges.TotalChanges()
|
||||||
}
|
}
|
||||||
for k := range o.SecurityRequirementChanges {
|
for k := range o.SecurityRequirementChanges {
|
||||||
c += o.SecurityRequirementChanges[k].TotalChanges()
|
c += o.SecurityRequirementChanges[k].TotalChanges()
|
||||||
}
|
}
|
||||||
if o.RequestBodyChanges != nil {
|
if o.RequestBodyChanges != nil {
|
||||||
c += o.RequestBodyChanges.TotalChanges()
|
c += o.RequestBodyChanges.TotalChanges()
|
||||||
}
|
}
|
||||||
for k := range o.ServerChanges {
|
for k := range o.ServerChanges {
|
||||||
c += o.ServerChanges[k].TotalChanges()
|
c += o.ServerChanges[k].TotalChanges()
|
||||||
}
|
}
|
||||||
for k := range o.CallbackChanges {
|
for k := range o.CallbackChanges {
|
||||||
c += o.CallbackChanges[k].TotalChanges()
|
c += o.CallbackChanges[k].TotalChanges()
|
||||||
}
|
}
|
||||||
if o.ExtensionChanges != nil {
|
if o.ExtensionChanges != nil {
|
||||||
c += o.ExtensionChanges.TotalChanges()
|
c += o.ExtensionChanges.TotalChanges()
|
||||||
}
|
}
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// TotalBreakingChanges returns the total number of breaking changes made between two Swagger
|
// TotalBreakingChanges returns the total number of breaking changes made between two Swagger
|
||||||
// or OpenAPI Operation objects.
|
// or OpenAPI Operation objects.
|
||||||
func (o *OperationChanges) TotalBreakingChanges() int {
|
func (o *OperationChanges) TotalBreakingChanges() int {
|
||||||
c := o.PropertyChanges.TotalBreakingChanges()
|
c := o.PropertyChanges.TotalBreakingChanges()
|
||||||
if o.ExternalDocChanges != nil {
|
if o.ExternalDocChanges != nil {
|
||||||
c += o.ExternalDocChanges.TotalBreakingChanges()
|
c += o.ExternalDocChanges.TotalBreakingChanges()
|
||||||
}
|
}
|
||||||
for k := range o.ParameterChanges {
|
for k := range o.ParameterChanges {
|
||||||
c += o.ParameterChanges[k].TotalBreakingChanges()
|
c += o.ParameterChanges[k].TotalBreakingChanges()
|
||||||
}
|
}
|
||||||
if o.ResponsesChanges != nil {
|
if o.ResponsesChanges != nil {
|
||||||
c += o.ResponsesChanges.TotalBreakingChanges()
|
c += o.ResponsesChanges.TotalBreakingChanges()
|
||||||
}
|
}
|
||||||
for k := range o.SecurityRequirementChanges {
|
for k := range o.SecurityRequirementChanges {
|
||||||
c += o.SecurityRequirementChanges[k].TotalBreakingChanges()
|
c += o.SecurityRequirementChanges[k].TotalBreakingChanges()
|
||||||
}
|
}
|
||||||
for k := range o.CallbackChanges {
|
for k := range o.CallbackChanges {
|
||||||
c += o.CallbackChanges[k].TotalBreakingChanges()
|
c += o.CallbackChanges[k].TotalBreakingChanges()
|
||||||
}
|
}
|
||||||
if o.RequestBodyChanges != nil {
|
if o.RequestBodyChanges != nil {
|
||||||
c += o.RequestBodyChanges.TotalBreakingChanges()
|
c += o.RequestBodyChanges.TotalBreakingChanges()
|
||||||
}
|
}
|
||||||
for k := range o.ServerChanges {
|
for k := range o.ServerChanges {
|
||||||
c += o.ServerChanges[k].TotalBreakingChanges()
|
c += o.ServerChanges[k].TotalBreakingChanges()
|
||||||
}
|
}
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for properties shared between operations objects.
|
// check for properties shared between operations objects.
|
||||||
func addSharedOperationProperties(left, right low.SharedOperations, changes *[]*Change) []*PropertyCheck {
|
func addSharedOperationProperties(left, right low.SharedOperations, changes *[]*Change) []*PropertyCheck {
|
||||||
var props []*PropertyCheck
|
var props []*PropertyCheck
|
||||||
|
|
||||||
// tags
|
// tags
|
||||||
if len(left.GetTags().Value) > 0 || len(right.GetTags().Value) > 0 {
|
if len(left.GetTags().Value) > 0 || len(right.GetTags().Value) > 0 {
|
||||||
ExtractStringValueSliceChanges(left.GetTags().Value, right.GetTags().Value,
|
ExtractStringValueSliceChanges(left.GetTags().Value, right.GetTags().Value,
|
||||||
changes, v3.TagsLabel, false)
|
changes, v3.TagsLabel, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// summary
|
// summary
|
||||||
addPropertyCheck(&props, left.GetSummary().ValueNode, right.GetSummary().ValueNode,
|
addPropertyCheck(&props, left.GetSummary().ValueNode, right.GetSummary().ValueNode,
|
||||||
left.GetSummary(), right.GetSummary(), changes, v3.SummaryLabel, false)
|
left.GetSummary(), right.GetSummary(), changes, v3.SummaryLabel, false)
|
||||||
|
|
||||||
// description
|
// description
|
||||||
addPropertyCheck(&props, left.GetDescription().ValueNode, right.GetDescription().ValueNode,
|
addPropertyCheck(&props, left.GetDescription().ValueNode, right.GetDescription().ValueNode,
|
||||||
left.GetDescription(), right.GetDescription(), changes, v3.DescriptionLabel, false)
|
left.GetDescription(), right.GetDescription(), changes, v3.DescriptionLabel, false)
|
||||||
|
|
||||||
// deprecated
|
// deprecated
|
||||||
addPropertyCheck(&props, left.GetDeprecated().ValueNode, right.GetDeprecated().ValueNode,
|
addPropertyCheck(&props, left.GetDeprecated().ValueNode, right.GetDeprecated().ValueNode,
|
||||||
left.GetDeprecated(), right.GetDeprecated(), changes, v3.DeprecatedLabel, false)
|
left.GetDeprecated(), right.GetDeprecated(), changes, v3.DeprecatedLabel, false)
|
||||||
|
|
||||||
// operation id
|
// operation id
|
||||||
addPropertyCheck(&props, left.GetOperationId().ValueNode, right.GetOperationId().ValueNode,
|
addPropertyCheck(&props, left.GetOperationId().ValueNode, right.GetOperationId().ValueNode,
|
||||||
left.GetOperationId(), right.GetOperationId(), changes, v3.OperationIdLabel, true)
|
left.GetOperationId(), right.GetOperationId(), changes, v3.OperationIdLabel, true)
|
||||||
|
|
||||||
return props
|
return props
|
||||||
}
|
}
|
||||||
|
|
||||||
// check shared objects
|
// check shared objects
|
||||||
func compareSharedOperationObjects(l, r low.SharedOperations, changes *[]*Change, opChanges *OperationChanges) {
|
func compareSharedOperationObjects(l, r low.SharedOperations, changes *[]*Change, opChanges *OperationChanges) {
|
||||||
|
|
||||||
// external docs
|
// external docs
|
||||||
if !l.GetExternalDocs().IsEmpty() && !r.GetExternalDocs().IsEmpty() {
|
if !l.GetExternalDocs().IsEmpty() && !r.GetExternalDocs().IsEmpty() {
|
||||||
lExtDoc := l.GetExternalDocs().Value.(*base.ExternalDoc)
|
lExtDoc := l.GetExternalDocs().Value.(*base.ExternalDoc)
|
||||||
rExtDoc := r.GetExternalDocs().Value.(*base.ExternalDoc)
|
rExtDoc := r.GetExternalDocs().Value.(*base.ExternalDoc)
|
||||||
if !low.AreEqual(lExtDoc, rExtDoc) {
|
if !low.AreEqual(lExtDoc, rExtDoc) {
|
||||||
opChanges.ExternalDocChanges = CompareExternalDocs(lExtDoc, rExtDoc)
|
opChanges.ExternalDocChanges = CompareExternalDocs(lExtDoc, rExtDoc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if l.GetExternalDocs().IsEmpty() && !r.GetExternalDocs().IsEmpty() {
|
if l.GetExternalDocs().IsEmpty() && !r.GetExternalDocs().IsEmpty() {
|
||||||
CreateChange(changes, PropertyAdded, v3.ExternalDocsLabel,
|
CreateChange(changes, PropertyAdded, v3.ExternalDocsLabel,
|
||||||
nil, r.GetExternalDocs().ValueNode, false, nil,
|
nil, r.GetExternalDocs().ValueNode, false, nil,
|
||||||
r.GetExternalDocs().Value)
|
r.GetExternalDocs().Value)
|
||||||
}
|
}
|
||||||
if !l.GetExternalDocs().IsEmpty() && r.GetExternalDocs().IsEmpty() {
|
if !l.GetExternalDocs().IsEmpty() && r.GetExternalDocs().IsEmpty() {
|
||||||
CreateChange(changes, PropertyRemoved, v3.ExternalDocsLabel,
|
CreateChange(changes, PropertyRemoved, v3.ExternalDocsLabel,
|
||||||
l.GetExternalDocs().ValueNode, nil, false, l.GetExternalDocs().Value,
|
l.GetExternalDocs().ValueNode, nil, false, l.GetExternalDocs().Value,
|
||||||
nil)
|
nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// responses
|
// responses
|
||||||
if !l.GetResponses().IsEmpty() && !r.GetResponses().IsEmpty() {
|
if !l.GetResponses().IsEmpty() && !r.GetResponses().IsEmpty() {
|
||||||
opChanges.ResponsesChanges = CompareResponses(l.GetResponses().Value, r.GetResponses().Value)
|
opChanges.ResponsesChanges = CompareResponses(l.GetResponses().Value, r.GetResponses().Value)
|
||||||
}
|
}
|
||||||
if l.GetResponses().IsEmpty() && !r.GetResponses().IsEmpty() {
|
if l.GetResponses().IsEmpty() && !r.GetResponses().IsEmpty() {
|
||||||
CreateChange(changes, PropertyAdded, v3.ResponsesLabel,
|
CreateChange(changes, PropertyAdded, v3.ResponsesLabel,
|
||||||
nil, r.GetResponses().ValueNode, false, nil,
|
nil, r.GetResponses().ValueNode, false, nil,
|
||||||
r.GetResponses().Value)
|
r.GetResponses().Value)
|
||||||
}
|
}
|
||||||
if !l.GetResponses().IsEmpty() && r.GetResponses().IsEmpty() {
|
if !l.GetResponses().IsEmpty() && r.GetResponses().IsEmpty() {
|
||||||
CreateChange(changes, PropertyRemoved, v3.ResponsesLabel,
|
CreateChange(changes, PropertyRemoved, v3.ResponsesLabel,
|
||||||
l.GetResponses().ValueNode, nil, true, l.GetResponses().Value,
|
l.GetResponses().ValueNode, nil, true, l.GetResponses().Value,
|
||||||
nil)
|
nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,371 +160,371 @@ func compareSharedOperationObjects(l, r low.SharedOperations, changes *[]*Change
|
|||||||
// a pointer to an OperationChanges instance, or nil if nothing is found.
|
// a pointer to an OperationChanges instance, or nil if nothing is found.
|
||||||
func CompareOperations(l, r any) *OperationChanges {
|
func CompareOperations(l, r any) *OperationChanges {
|
||||||
|
|
||||||
var changes []*Change
|
var changes []*Change
|
||||||
var props []*PropertyCheck
|
var props []*PropertyCheck
|
||||||
|
|
||||||
oc := new(OperationChanges)
|
oc := new(OperationChanges)
|
||||||
|
|
||||||
// Swagger
|
// Swagger
|
||||||
if reflect.TypeOf(&v2.Operation{}) == reflect.TypeOf(l) &&
|
if reflect.TypeOf(&v2.Operation{}) == reflect.TypeOf(l) &&
|
||||||
reflect.TypeOf(&v2.Operation{}) == reflect.TypeOf(r) {
|
reflect.TypeOf(&v2.Operation{}) == reflect.TypeOf(r) {
|
||||||
|
|
||||||
lOperation := l.(*v2.Operation)
|
lOperation := l.(*v2.Operation)
|
||||||
rOperation := r.(*v2.Operation)
|
rOperation := r.(*v2.Operation)
|
||||||
|
|
||||||
// perform hash check to avoid further processing
|
// perform hash check to avoid further processing
|
||||||
if low.AreEqual(lOperation, rOperation) {
|
if low.AreEqual(lOperation, rOperation) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
props = append(props, addSharedOperationProperties(lOperation, rOperation, &changes)...)
|
props = append(props, addSharedOperationProperties(lOperation, rOperation, &changes)...)
|
||||||
|
|
||||||
compareSharedOperationObjects(lOperation, rOperation, &changes, oc)
|
compareSharedOperationObjects(lOperation, rOperation, &changes, oc)
|
||||||
|
|
||||||
// parameters
|
// parameters
|
||||||
lParamsUntyped := lOperation.GetParameters()
|
lParamsUntyped := lOperation.GetParameters()
|
||||||
rParamsUntyped := rOperation.GetParameters()
|
rParamsUntyped := rOperation.GetParameters()
|
||||||
if !lParamsUntyped.IsEmpty() && !rParamsUntyped.IsEmpty() {
|
if !lParamsUntyped.IsEmpty() && !rParamsUntyped.IsEmpty() {
|
||||||
lParams := lParamsUntyped.Value.([]low.ValueReference[*v2.Parameter])
|
lParams := lParamsUntyped.Value.([]low.ValueReference[*v2.Parameter])
|
||||||
rParams := rParamsUntyped.Value.([]low.ValueReference[*v2.Parameter])
|
rParams := rParamsUntyped.Value.([]low.ValueReference[*v2.Parameter])
|
||||||
|
|
||||||
lv := make(map[string]*v2.Parameter, len(lParams))
|
lv := make(map[string]*v2.Parameter, len(lParams))
|
||||||
rv := make(map[string]*v2.Parameter, len(rParams))
|
rv := make(map[string]*v2.Parameter, len(rParams))
|
||||||
|
|
||||||
for i := range lParams {
|
for i := range lParams {
|
||||||
s := lParams[i].Value.Name.Value
|
s := lParams[i].Value.Name.Value
|
||||||
lv[s] = lParams[i].Value
|
lv[s] = lParams[i].Value
|
||||||
}
|
}
|
||||||
for i := range rParams {
|
for i := range rParams {
|
||||||
s := rParams[i].Value.Name.Value
|
s := rParams[i].Value.Name.Value
|
||||||
rv[s] = rParams[i].Value
|
rv[s] = rParams[i].Value
|
||||||
}
|
}
|
||||||
|
|
||||||
var paramChanges []*ParameterChanges
|
var paramChanges []*ParameterChanges
|
||||||
for n := range lv {
|
for n := range lv {
|
||||||
if _, ok := rv[n]; ok {
|
if _, ok := rv[n]; ok {
|
||||||
if !low.AreEqual(lv[n], rv[n]) {
|
if !low.AreEqual(lv[n], rv[n]) {
|
||||||
ch := CompareParameters(lv[n], rv[n])
|
ch := CompareParameters(lv[n], rv[n])
|
||||||
if ch != nil {
|
if ch != nil {
|
||||||
paramChanges = append(paramChanges, ch)
|
paramChanges = append(paramChanges, ch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
CreateChange(&changes, ObjectRemoved, v3.ParametersLabel,
|
CreateChange(&changes, ObjectRemoved, v3.ParametersLabel,
|
||||||
lv[n].Name.ValueNode, nil, true, lv[n].Name.Value,
|
lv[n].Name.ValueNode, nil, true, lv[n].Name.Value,
|
||||||
nil)
|
nil)
|
||||||
|
|
||||||
}
|
}
|
||||||
for n := range rv {
|
for n := range rv {
|
||||||
if _, ok := lv[n]; !ok {
|
if _, ok := lv[n]; !ok {
|
||||||
CreateChange(&changes, ObjectAdded, v3.ParametersLabel,
|
CreateChange(&changes, ObjectAdded, v3.ParametersLabel,
|
||||||
nil, rv[n].Name.ValueNode, true, nil,
|
nil, rv[n].Name.ValueNode, true, nil,
|
||||||
rv[n].Name.Value)
|
rv[n].Name.Value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
oc.ParameterChanges = paramChanges
|
oc.ParameterChanges = paramChanges
|
||||||
}
|
}
|
||||||
if !lParamsUntyped.IsEmpty() && rParamsUntyped.IsEmpty() {
|
if !lParamsUntyped.IsEmpty() && rParamsUntyped.IsEmpty() {
|
||||||
CreateChange(&changes, PropertyRemoved, v3.ParametersLabel,
|
CreateChange(&changes, PropertyRemoved, v3.ParametersLabel,
|
||||||
lParamsUntyped.ValueNode, nil, true, lParamsUntyped.Value,
|
lParamsUntyped.ValueNode, nil, true, lParamsUntyped.Value,
|
||||||
nil)
|
nil)
|
||||||
}
|
}
|
||||||
if lParamsUntyped.IsEmpty() && !rParamsUntyped.IsEmpty() {
|
if lParamsUntyped.IsEmpty() && !rParamsUntyped.IsEmpty() {
|
||||||
CreateChange(&changes, PropertyAdded, v3.ParametersLabel,
|
CreateChange(&changes, PropertyAdded, v3.ParametersLabel,
|
||||||
nil, rParamsUntyped.ValueNode, true, nil,
|
nil, rParamsUntyped.ValueNode, true, nil,
|
||||||
rParamsUntyped.Value)
|
rParamsUntyped.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// security
|
// security
|
||||||
if !lOperation.Security.IsEmpty() || !rOperation.Security.IsEmpty() {
|
if !lOperation.Security.IsEmpty() || !rOperation.Security.IsEmpty() {
|
||||||
checkSecurity(lOperation.Security, rOperation.Security, &changes, oc)
|
checkSecurity(lOperation.Security, rOperation.Security, &changes, oc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// produces
|
// produces
|
||||||
if len(lOperation.Produces.Value) > 0 || len(rOperation.Produces.Value) > 0 {
|
if len(lOperation.Produces.Value) > 0 || len(rOperation.Produces.Value) > 0 {
|
||||||
ExtractStringValueSliceChanges(lOperation.Produces.Value, rOperation.Produces.Value,
|
ExtractStringValueSliceChanges(lOperation.Produces.Value, rOperation.Produces.Value,
|
||||||
&changes, v3.ProducesLabel, true)
|
&changes, v3.ProducesLabel, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// consumes
|
// consumes
|
||||||
if len(lOperation.Consumes.Value) > 0 || len(rOperation.Consumes.Value) > 0 {
|
if len(lOperation.Consumes.Value) > 0 || len(rOperation.Consumes.Value) > 0 {
|
||||||
ExtractStringValueSliceChanges(lOperation.Consumes.Value, rOperation.Consumes.Value,
|
ExtractStringValueSliceChanges(lOperation.Consumes.Value, rOperation.Consumes.Value,
|
||||||
&changes, v3.ConsumesLabel, true)
|
&changes, v3.ConsumesLabel, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// schemes
|
// schemes
|
||||||
if len(lOperation.Schemes.Value) > 0 || len(rOperation.Schemes.Value) > 0 {
|
if len(lOperation.Schemes.Value) > 0 || len(rOperation.Schemes.Value) > 0 {
|
||||||
ExtractStringValueSliceChanges(lOperation.Schemes.Value, rOperation.Schemes.Value,
|
ExtractStringValueSliceChanges(lOperation.Schemes.Value, rOperation.Schemes.Value,
|
||||||
&changes, v3.SchemesLabel, true)
|
&changes, v3.SchemesLabel, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
oc.ExtensionChanges = CompareExtensions(lOperation.Extensions, rOperation.Extensions)
|
oc.ExtensionChanges = CompareExtensions(lOperation.Extensions, rOperation.Extensions)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenAPI
|
// OpenAPI
|
||||||
if reflect.TypeOf(&v3.Operation{}) == reflect.TypeOf(l) &&
|
if reflect.TypeOf(&v3.Operation{}) == reflect.TypeOf(l) &&
|
||||||
reflect.TypeOf(&v3.Operation{}) == reflect.TypeOf(r) {
|
reflect.TypeOf(&v3.Operation{}) == reflect.TypeOf(r) {
|
||||||
|
|
||||||
lOperation := l.(*v3.Operation)
|
lOperation := l.(*v3.Operation)
|
||||||
rOperation := r.(*v3.Operation)
|
rOperation := r.(*v3.Operation)
|
||||||
|
|
||||||
// perform hash check to avoid further processing
|
// perform hash check to avoid further processing
|
||||||
if low.AreEqual(lOperation, rOperation) {
|
if low.AreEqual(lOperation, rOperation) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
props = append(props, addSharedOperationProperties(lOperation, rOperation, &changes)...)
|
props = append(props, addSharedOperationProperties(lOperation, rOperation, &changes)...)
|
||||||
compareSharedOperationObjects(lOperation, rOperation, &changes, oc)
|
compareSharedOperationObjects(lOperation, rOperation, &changes, oc)
|
||||||
|
|
||||||
// parameters
|
// parameters
|
||||||
lParamsUntyped := lOperation.GetParameters()
|
lParamsUntyped := lOperation.GetParameters()
|
||||||
rParamsUntyped := rOperation.GetParameters()
|
rParamsUntyped := rOperation.GetParameters()
|
||||||
if !lParamsUntyped.IsEmpty() && !rParamsUntyped.IsEmpty() {
|
if !lParamsUntyped.IsEmpty() && !rParamsUntyped.IsEmpty() {
|
||||||
lParams := lParamsUntyped.Value.([]low.ValueReference[*v3.Parameter])
|
lParams := lParamsUntyped.Value.([]low.ValueReference[*v3.Parameter])
|
||||||
rParams := rParamsUntyped.Value.([]low.ValueReference[*v3.Parameter])
|
rParams := rParamsUntyped.Value.([]low.ValueReference[*v3.Parameter])
|
||||||
|
|
||||||
lv := make(map[string]*v3.Parameter, len(lParams))
|
lv := make(map[string]*v3.Parameter, len(lParams))
|
||||||
rv := make(map[string]*v3.Parameter, len(rParams))
|
rv := make(map[string]*v3.Parameter, len(rParams))
|
||||||
|
|
||||||
for i := range lParams {
|
for i := range lParams {
|
||||||
s := lParams[i].Value.Name.Value
|
s := lParams[i].Value.Name.Value
|
||||||
lv[s] = lParams[i].Value
|
lv[s] = lParams[i].Value
|
||||||
}
|
}
|
||||||
for i := range rParams {
|
for i := range rParams {
|
||||||
s := rParams[i].Value.Name.Value
|
s := rParams[i].Value.Name.Value
|
||||||
rv[s] = rParams[i].Value
|
rv[s] = rParams[i].Value
|
||||||
}
|
}
|
||||||
|
|
||||||
var paramChanges []*ParameterChanges
|
var paramChanges []*ParameterChanges
|
||||||
for n := range lv {
|
for n := range lv {
|
||||||
if _, ok := rv[n]; ok {
|
if _, ok := rv[n]; ok {
|
||||||
if !low.AreEqual(lv[n], rv[n]) {
|
if !low.AreEqual(lv[n], rv[n]) {
|
||||||
ch := CompareParameters(lv[n], rv[n])
|
ch := CompareParameters(lv[n], rv[n])
|
||||||
if ch != nil {
|
if ch != nil {
|
||||||
paramChanges = append(paramChanges, ch)
|
paramChanges = append(paramChanges, ch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
CreateChange(&changes, ObjectRemoved, v3.ParametersLabel,
|
CreateChange(&changes, ObjectRemoved, v3.ParametersLabel,
|
||||||
lv[n].Name.ValueNode, nil, true, lv[n].Name.Value,
|
lv[n].Name.ValueNode, nil, true, lv[n].Name.Value,
|
||||||
nil)
|
nil)
|
||||||
|
|
||||||
}
|
}
|
||||||
for n := range rv {
|
for n := range rv {
|
||||||
if _, ok := lv[n]; !ok {
|
if _, ok := lv[n]; !ok {
|
||||||
CreateChange(&changes, ObjectAdded, v3.ParametersLabel,
|
CreateChange(&changes, ObjectAdded, v3.ParametersLabel,
|
||||||
nil, rv[n].Name.ValueNode, true, nil,
|
nil, rv[n].Name.ValueNode, true, nil,
|
||||||
rv[n].Name.Value)
|
rv[n].Name.Value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
oc.ParameterChanges = paramChanges
|
oc.ParameterChanges = paramChanges
|
||||||
}
|
}
|
||||||
if !lParamsUntyped.IsEmpty() && rParamsUntyped.IsEmpty() {
|
if !lParamsUntyped.IsEmpty() && rParamsUntyped.IsEmpty() {
|
||||||
CreateChange(&changes, PropertyRemoved, v3.ParametersLabel,
|
CreateChange(&changes, PropertyRemoved, v3.ParametersLabel,
|
||||||
lParamsUntyped.ValueNode, nil, true, lParamsUntyped.Value,
|
lParamsUntyped.ValueNode, nil, true, lParamsUntyped.Value,
|
||||||
nil)
|
nil)
|
||||||
}
|
}
|
||||||
if lParamsUntyped.IsEmpty() && !rParamsUntyped.IsEmpty() {
|
if lParamsUntyped.IsEmpty() && !rParamsUntyped.IsEmpty() {
|
||||||
CreateChange(&changes, PropertyAdded, v3.ParametersLabel,
|
CreateChange(&changes, PropertyAdded, v3.ParametersLabel,
|
||||||
nil, rParamsUntyped.ValueNode, true, nil,
|
nil, rParamsUntyped.ValueNode, true, nil,
|
||||||
rParamsUntyped.Value)
|
rParamsUntyped.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// security
|
// security
|
||||||
if !lOperation.Security.IsEmpty() && !lOperation.Security.IsEmpty() {
|
if !lOperation.Security.IsEmpty() && !lOperation.Security.IsEmpty() {
|
||||||
checkSecurity(lOperation.Security, rOperation.Security, &changes, oc)
|
checkSecurity(lOperation.Security, rOperation.Security, &changes, oc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// request body
|
// request body
|
||||||
if !lOperation.RequestBody.IsEmpty() && !rOperation.RequestBody.IsEmpty() {
|
if !lOperation.RequestBody.IsEmpty() && !rOperation.RequestBody.IsEmpty() {
|
||||||
if !low.AreEqual(lOperation.RequestBody.Value, rOperation.RequestBody.Value) {
|
if !low.AreEqual(lOperation.RequestBody.Value, rOperation.RequestBody.Value) {
|
||||||
oc.RequestBodyChanges = CompareRequestBodies(lOperation.RequestBody.Value, rOperation.RequestBody.Value)
|
oc.RequestBodyChanges = CompareRequestBodies(lOperation.RequestBody.Value, rOperation.RequestBody.Value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !lOperation.RequestBody.IsEmpty() && rOperation.RequestBody.IsEmpty() {
|
if !lOperation.RequestBody.IsEmpty() && rOperation.RequestBody.IsEmpty() {
|
||||||
CreateChange(&changes, PropertyRemoved, v3.RequestBodyLabel,
|
CreateChange(&changes, PropertyRemoved, v3.RequestBodyLabel,
|
||||||
lOperation.RequestBody.ValueNode, nil, true, lOperation.RequestBody.Value,
|
lOperation.RequestBody.ValueNode, nil, true, lOperation.RequestBody.Value,
|
||||||
nil)
|
nil)
|
||||||
}
|
}
|
||||||
if lOperation.RequestBody.IsEmpty() && !rOperation.RequestBody.IsEmpty() {
|
if lOperation.RequestBody.IsEmpty() && !rOperation.RequestBody.IsEmpty() {
|
||||||
CreateChange(&changes, PropertyAdded, v3.RequestBodyLabel,
|
CreateChange(&changes, PropertyAdded, v3.RequestBodyLabel,
|
||||||
nil, rOperation.RequestBody.ValueNode, true, nil,
|
nil, rOperation.RequestBody.ValueNode, true, nil,
|
||||||
rOperation.RequestBody.Value)
|
rOperation.RequestBody.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// callbacks
|
// callbacks
|
||||||
if !lOperation.GetCallbacks().IsEmpty() && !rOperation.GetCallbacks().IsEmpty() {
|
if !lOperation.GetCallbacks().IsEmpty() && !rOperation.GetCallbacks().IsEmpty() {
|
||||||
oc.CallbackChanges = CheckMapForChanges(lOperation.Callbacks.Value, rOperation.Callbacks.Value, &changes,
|
oc.CallbackChanges = CheckMapForChanges(lOperation.Callbacks.Value, rOperation.Callbacks.Value, &changes,
|
||||||
v3.CallbacksLabel, CompareCallback)
|
v3.CallbacksLabel, CompareCallback)
|
||||||
}
|
}
|
||||||
if !lOperation.GetCallbacks().IsEmpty() && rOperation.GetCallbacks().IsEmpty() {
|
if !lOperation.GetCallbacks().IsEmpty() && rOperation.GetCallbacks().IsEmpty() {
|
||||||
CreateChange(&changes, PropertyRemoved, v3.CallbacksLabel,
|
CreateChange(&changes, PropertyRemoved, v3.CallbacksLabel,
|
||||||
lOperation.Callbacks.ValueNode, nil, true, lOperation.Callbacks.Value,
|
lOperation.Callbacks.ValueNode, nil, true, lOperation.Callbacks.Value,
|
||||||
nil)
|
nil)
|
||||||
}
|
}
|
||||||
if lOperation.Callbacks.IsEmpty() && !rOperation.Callbacks.IsEmpty() {
|
if lOperation.Callbacks.IsEmpty() && !rOperation.Callbacks.IsEmpty() {
|
||||||
CreateChange(&changes, PropertyAdded, v3.CallbacksLabel,
|
CreateChange(&changes, PropertyAdded, v3.CallbacksLabel,
|
||||||
nil, rOperation.Callbacks.ValueNode, false, nil,
|
nil, rOperation.Callbacks.ValueNode, false, nil,
|
||||||
rOperation.Callbacks.Value)
|
rOperation.Callbacks.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// servers
|
// servers
|
||||||
oc.ServerChanges = checkServers(lOperation.Servers, rOperation.Servers)
|
oc.ServerChanges = checkServers(lOperation.Servers, rOperation.Servers)
|
||||||
oc.ExtensionChanges = CompareExtensions(lOperation.Extensions, rOperation.Extensions)
|
oc.ExtensionChanges = CompareExtensions(lOperation.Extensions, rOperation.Extensions)
|
||||||
|
|
||||||
// todo: callbacks
|
// todo: callbacks
|
||||||
}
|
}
|
||||||
CheckProperties(props)
|
CheckProperties(props)
|
||||||
oc.PropertyChanges = NewPropertyChanges(changes)
|
oc.PropertyChanges = NewPropertyChanges(changes)
|
||||||
return oc
|
return oc
|
||||||
}
|
}
|
||||||
|
|
||||||
// check servers property
|
// check servers property
|
||||||
func checkServers(lServers, rServers low.NodeReference[[]low.ValueReference[*v3.Server]]) []*ServerChanges {
|
func checkServers(lServers, rServers low.NodeReference[[]low.ValueReference[*v3.Server]]) []*ServerChanges {
|
||||||
|
|
||||||
var serverChanges []*ServerChanges
|
var serverChanges []*ServerChanges
|
||||||
|
|
||||||
if !lServers.IsEmpty() && !rServers.IsEmpty() {
|
if !lServers.IsEmpty() && !rServers.IsEmpty() {
|
||||||
|
|
||||||
lv := make(map[string]low.ValueReference[*v3.Server], len(lServers.Value))
|
lv := make(map[string]low.ValueReference[*v3.Server], len(lServers.Value))
|
||||||
rv := make(map[string]low.ValueReference[*v3.Server], len(rServers.Value))
|
rv := make(map[string]low.ValueReference[*v3.Server], len(rServers.Value))
|
||||||
|
|
||||||
for i := range lServers.Value {
|
for i := range lServers.Value {
|
||||||
var s string
|
var s string
|
||||||
if !lServers.Value[i].Value.URL.IsEmpty() {
|
if !lServers.Value[i].Value.URL.IsEmpty() {
|
||||||
s = lServers.Value[i].Value.URL.Value
|
s = lServers.Value[i].Value.URL.Value
|
||||||
} else {
|
} else {
|
||||||
s = low.GenerateHashString(lServers.Value[i].Value)
|
s = low.GenerateHashString(lServers.Value[i].Value)
|
||||||
}
|
}
|
||||||
lv[s] = lServers.Value[i]
|
lv[s] = lServers.Value[i]
|
||||||
}
|
}
|
||||||
for i := range rServers.Value {
|
for i := range rServers.Value {
|
||||||
var s string
|
var s string
|
||||||
if !rServers.Value[i].Value.URL.IsEmpty() {
|
if !rServers.Value[i].Value.URL.IsEmpty() {
|
||||||
s = rServers.Value[i].Value.URL.Value
|
s = rServers.Value[i].Value.URL.Value
|
||||||
} else {
|
} else {
|
||||||
s = low.GenerateHashString(rServers.Value[i].Value)
|
s = low.GenerateHashString(rServers.Value[i].Value)
|
||||||
}
|
}
|
||||||
rv[s] = rServers.Value[i]
|
rv[s] = rServers.Value[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
for k := range lv {
|
for k := range lv {
|
||||||
|
|
||||||
var changes []*Change
|
var changes []*Change
|
||||||
|
|
||||||
if _, ok := rv[k]; ok {
|
if _, ok := rv[k]; ok {
|
||||||
if !low.AreEqual(lv[k].Value, rv[k].Value) {
|
if !low.AreEqual(lv[k].Value, rv[k].Value) {
|
||||||
serverChanges = append(serverChanges, CompareServers(lv[k].Value, rv[k].Value))
|
serverChanges = append(serverChanges, CompareServers(lv[k].Value, rv[k].Value))
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
lv[k].ValueNode.Value = lv[k].Value.URL.Value
|
lv[k].ValueNode.Value = lv[k].Value.URL.Value
|
||||||
CreateChange(&changes, ObjectRemoved, v3.ServersLabel,
|
CreateChange(&changes, ObjectRemoved, v3.ServersLabel,
|
||||||
lv[k].ValueNode, nil, true, lv[k].Value.URL.Value,
|
lv[k].ValueNode, nil, true, lv[k].Value.URL.Value,
|
||||||
nil)
|
nil)
|
||||||
sc := new(ServerChanges)
|
sc := new(ServerChanges)
|
||||||
sc.PropertyChanges = NewPropertyChanges(changes)
|
sc.PropertyChanges = NewPropertyChanges(changes)
|
||||||
serverChanges = append(serverChanges, sc)
|
serverChanges = append(serverChanges, sc)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for k := range rv {
|
for k := range rv {
|
||||||
|
|
||||||
if _, ok := lv[k]; !ok {
|
if _, ok := lv[k]; !ok {
|
||||||
|
|
||||||
var changes []*Change
|
var changes []*Change
|
||||||
rv[k].ValueNode.Value = rv[k].Value.URL.Value
|
rv[k].ValueNode.Value = rv[k].Value.URL.Value
|
||||||
CreateChange(&changes, ObjectAdded, v3.ServersLabel,
|
CreateChange(&changes, ObjectAdded, v3.ServersLabel,
|
||||||
nil, rv[k].ValueNode, false, nil,
|
nil, rv[k].ValueNode, false, nil,
|
||||||
rv[k].Value.URL.Value)
|
rv[k].Value.URL.Value)
|
||||||
|
|
||||||
sc := new(ServerChanges)
|
sc := new(ServerChanges)
|
||||||
sc.PropertyChanges = NewPropertyChanges(changes)
|
sc.PropertyChanges = NewPropertyChanges(changes)
|
||||||
serverChanges = append(serverChanges, sc)
|
serverChanges = append(serverChanges, sc)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var changes []*Change
|
var changes []*Change
|
||||||
sc := new(ServerChanges)
|
sc := new(ServerChanges)
|
||||||
if !lServers.IsEmpty() && rServers.IsEmpty() {
|
if !lServers.IsEmpty() && rServers.IsEmpty() {
|
||||||
CreateChange(&changes, PropertyRemoved, v3.ServersLabel,
|
CreateChange(&changes, PropertyRemoved, v3.ServersLabel,
|
||||||
lServers.ValueNode, nil, true, lServers.Value,
|
lServers.ValueNode, nil, true, lServers.Value,
|
||||||
nil)
|
nil)
|
||||||
}
|
}
|
||||||
if lServers.IsEmpty() && !rServers.IsEmpty() {
|
if lServers.IsEmpty() && !rServers.IsEmpty() {
|
||||||
CreateChange(&changes, PropertyAdded, v3.ServersLabel,
|
CreateChange(&changes, PropertyAdded, v3.ServersLabel,
|
||||||
nil, rServers.ValueNode, false, nil,
|
nil, rServers.ValueNode, false, nil,
|
||||||
rServers.Value)
|
rServers.Value)
|
||||||
}
|
}
|
||||||
sc.PropertyChanges = NewPropertyChanges(changes)
|
sc.PropertyChanges = NewPropertyChanges(changes)
|
||||||
if len(changes) > 0 {
|
if len(changes) > 0 {
|
||||||
serverChanges = append(serverChanges, sc)
|
serverChanges = append(serverChanges, sc)
|
||||||
}
|
}
|
||||||
if len(serverChanges) <= 0 {
|
if len(serverChanges) <= 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return serverChanges
|
return serverChanges
|
||||||
}
|
}
|
||||||
|
|
||||||
// check security property.
|
// check security property.
|
||||||
func checkSecurity(lSecurity, rSecurity low.NodeReference[[]low.ValueReference[*base.SecurityRequirement]],
|
func checkSecurity(lSecurity, rSecurity low.NodeReference[[]low.ValueReference[*base.SecurityRequirement]],
|
||||||
changes *[]*Change, oc any) {
|
changes *[]*Change, oc any) {
|
||||||
|
|
||||||
lv := make(map[string]*base.SecurityRequirement, len(lSecurity.Value))
|
lv := make(map[string]*base.SecurityRequirement, len(lSecurity.Value))
|
||||||
rv := make(map[string]*base.SecurityRequirement, len(rSecurity.Value))
|
rv := make(map[string]*base.SecurityRequirement, len(rSecurity.Value))
|
||||||
lvn := make(map[string]*yaml.Node, len(lSecurity.Value))
|
lvn := make(map[string]*yaml.Node, len(lSecurity.Value))
|
||||||
rvn := make(map[string]*yaml.Node, len(rSecurity.Value))
|
rvn := make(map[string]*yaml.Node, len(rSecurity.Value))
|
||||||
|
|
||||||
for i := range lSecurity.Value {
|
for i := range lSecurity.Value {
|
||||||
keys := lSecurity.Value[i].Value.GetKeys()
|
keys := lSecurity.Value[i].Value.GetKeys()
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
s := strings.Join(keys, "|")
|
s := strings.Join(keys, "|")
|
||||||
lv[s] = lSecurity.Value[i].Value
|
lv[s] = lSecurity.Value[i].Value
|
||||||
lvn[s] = lSecurity.Value[i].ValueNode
|
lvn[s] = lSecurity.Value[i].ValueNode
|
||||||
|
|
||||||
}
|
}
|
||||||
for i := range rSecurity.Value {
|
for i := range rSecurity.Value {
|
||||||
keys := rSecurity.Value[i].Value.GetKeys()
|
keys := rSecurity.Value[i].Value.GetKeys()
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
s := strings.Join(keys, "|")
|
s := strings.Join(keys, "|")
|
||||||
rv[s] = rSecurity.Value[i].Value
|
rv[s] = rSecurity.Value[i].Value
|
||||||
rvn[s] = rSecurity.Value[i].ValueNode
|
rvn[s] = rSecurity.Value[i].ValueNode
|
||||||
}
|
}
|
||||||
|
|
||||||
var secChanges []*SecurityRequirementChanges
|
var secChanges []*SecurityRequirementChanges
|
||||||
for n := range lv {
|
for n := range lv {
|
||||||
if _, ok := rv[n]; ok {
|
if _, ok := rv[n]; ok {
|
||||||
if !low.AreEqual(lv[n], rv[n]) {
|
if !low.AreEqual(lv[n], rv[n]) {
|
||||||
ch := CompareSecurityRequirement(lv[n], rv[n])
|
ch := CompareSecurityRequirement(lv[n], rv[n])
|
||||||
if ch != nil {
|
if ch != nil {
|
||||||
secChanges = append(secChanges, ch)
|
secChanges = append(secChanges, ch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
lvn[n].Value = strings.Join(lv[n].GetKeys(), ", ")
|
lvn[n].Value = strings.Join(lv[n].GetKeys(), ", ")
|
||||||
CreateChange(changes, ObjectRemoved, v3.SecurityLabel,
|
CreateChange(changes, ObjectRemoved, v3.SecurityLabel,
|
||||||
lvn[n], nil, true, lv[n],
|
lvn[n], nil, true, lv[n],
|
||||||
nil)
|
nil)
|
||||||
|
|
||||||
}
|
}
|
||||||
for n := range rv {
|
for n := range rv {
|
||||||
if _, ok := lv[n]; !ok {
|
if _, ok := lv[n]; !ok {
|
||||||
rvn[n].Value = strings.Join(rv[n].GetKeys(), ", ")
|
rvn[n].Value = strings.Join(rv[n].GetKeys(), ", ")
|
||||||
CreateChange(changes, ObjectAdded, v3.SecurityLabel,
|
CreateChange(changes, ObjectAdded, v3.SecurityLabel,
|
||||||
nil, rvn[n], false, nil,
|
nil, rvn[n], false, nil,
|
||||||
rv[n])
|
rv[n])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle different change types.
|
// handle different change types.
|
||||||
if reflect.TypeOf(&OperationChanges{}) == reflect.TypeOf(oc) {
|
if reflect.TypeOf(&OperationChanges{}) == reflect.TypeOf(oc) {
|
||||||
oc.(*OperationChanges).SecurityRequirementChanges = secChanges
|
oc.(*OperationChanges).SecurityRequirementChanges = secChanges
|
||||||
}
|
}
|
||||||
if reflect.TypeOf(&DocumentChanges{}) == reflect.TypeOf(oc) {
|
if reflect.TypeOf(&DocumentChanges{}) == reflect.TypeOf(oc) {
|
||||||
oc.(*DocumentChanges).SecurityRequirementChanges = secChanges
|
oc.(*DocumentChanges).SecurityRequirementChanges = secChanges
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user