123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499 |
- /*
- Copyright 2017 The Kubernetes Authors.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
- package aggregator
- import (
- _ "net/http/pprof"
- "github.com/go-openapi/spec"
- )
- // Run a walkRefCallback method on all references of an OpenAPI spec, replacing the values.
- type mutatingReferenceWalker struct {
- // walkRefCallback will be called on each reference. Do not mutate the input, always create a copy first and return that.
- walkRefCallback func(ref *spec.Ref) *spec.Ref
- }
- // replaceReferences rewrites the references without mutating the input.
- // The output might share data with the input.
- func replaceReferences(walkRef func(ref *spec.Ref) *spec.Ref, sp *spec.Swagger) *spec.Swagger {
- walker := &mutatingReferenceWalker{walkRefCallback: walkRef}
- return walker.Start(sp)
- }
- func (w *mutatingReferenceWalker) walkSchema(schema *spec.Schema) *spec.Schema {
- if schema == nil {
- return nil
- }
- orig := schema
- clone := func() {
- if orig == schema {
- schema = &spec.Schema{}
- *schema = *orig
- }
- }
- if r := w.walkRefCallback(&schema.Ref); r != &schema.Ref {
- clone()
- schema.Ref = *r
- }
- definitionsCloned := false
- for k, v := range schema.Definitions {
- if s := w.walkSchema(&v); s != &v {
- if !definitionsCloned {
- definitionsCloned = true
- clone()
- schema.Definitions = make(spec.Definitions, len(orig.Definitions))
- for k2, v2 := range orig.Definitions {
- schema.Definitions[k2] = v2
- }
- }
- schema.Definitions[k] = *s
- }
- }
- propertiesCloned := false
- for k, v := range schema.Properties {
- if s := w.walkSchema(&v); s != &v {
- if !propertiesCloned {
- propertiesCloned = true
- clone()
- schema.Properties = make(map[string]spec.Schema, len(orig.Properties))
- for k2, v2 := range orig.Properties {
- schema.Properties[k2] = v2
- }
- }
- schema.Properties[k] = *s
- }
- }
- patternPropertiesCloned := false
- for k, v := range schema.PatternProperties {
- if s := w.walkSchema(&v); s != &v {
- if !patternPropertiesCloned {
- patternPropertiesCloned = true
- clone()
- schema.PatternProperties = make(map[string]spec.Schema, len(orig.PatternProperties))
- for k2, v2 := range orig.PatternProperties {
- schema.PatternProperties[k2] = v2
- }
- }
- schema.PatternProperties[k] = *s
- }
- }
- allOfCloned := false
- for i := range schema.AllOf {
- if s := w.walkSchema(&schema.AllOf[i]); s != &schema.AllOf[i] {
- if !allOfCloned {
- allOfCloned = true
- clone()
- schema.AllOf = make([]spec.Schema, len(orig.AllOf))
- copy(schema.AllOf, orig.AllOf)
- }
- schema.AllOf[i] = *s
- }
- }
- anyOfCloned := false
- for i := range schema.AnyOf {
- if s := w.walkSchema(&schema.AnyOf[i]); s != &schema.AnyOf[i] {
- if !anyOfCloned {
- anyOfCloned = true
- clone()
- schema.AnyOf = make([]spec.Schema, len(orig.AnyOf))
- copy(schema.AnyOf, orig.AnyOf)
- }
- schema.AnyOf[i] = *s
- }
- }
- oneOfCloned := false
- for i := range schema.OneOf {
- if s := w.walkSchema(&schema.OneOf[i]); s != &schema.OneOf[i] {
- if !oneOfCloned {
- oneOfCloned = true
- clone()
- schema.OneOf = make([]spec.Schema, len(orig.OneOf))
- copy(schema.OneOf, orig.OneOf)
- }
- schema.OneOf[i] = *s
- }
- }
- if schema.Not != nil {
- if s := w.walkSchema(schema.Not); s != schema.Not {
- clone()
- schema.Not = s
- }
- }
- if schema.AdditionalProperties != nil && schema.AdditionalProperties.Schema != nil {
- if s := w.walkSchema(schema.AdditionalProperties.Schema); s != schema.AdditionalProperties.Schema {
- clone()
- schema.AdditionalProperties = &spec.SchemaOrBool{Schema: s, Allows: schema.AdditionalProperties.Allows}
- }
- }
- if schema.AdditionalItems != nil && schema.AdditionalItems.Schema != nil {
- if s := w.walkSchema(schema.AdditionalItems.Schema); s != schema.AdditionalItems.Schema {
- clone()
- schema.AdditionalItems = &spec.SchemaOrBool{Schema: s, Allows: schema.AdditionalItems.Allows}
- }
- }
- if schema.Items != nil {
- if schema.Items.Schema != nil {
- if s := w.walkSchema(schema.Items.Schema); s != schema.Items.Schema {
- clone()
- schema.Items = &spec.SchemaOrArray{Schema: s}
- }
- } else {
- itemsCloned := false
- for i := range schema.Items.Schemas {
- if s := w.walkSchema(&schema.Items.Schemas[i]); s != &schema.Items.Schemas[i] {
- if !itemsCloned {
- clone()
- schema.Items = &spec.SchemaOrArray{
- Schemas: make([]spec.Schema, len(orig.Items.Schemas)),
- }
- itemsCloned = true
- copy(schema.Items.Schemas, orig.Items.Schemas)
- }
- schema.Items.Schemas[i] = *s
- }
- }
- }
- }
- return schema
- }
- func (w *mutatingReferenceWalker) walkParameter(param *spec.Parameter) *spec.Parameter {
- if param == nil {
- return nil
- }
- orig := param
- cloned := false
- clone := func() {
- if !cloned {
- cloned = true
- param = &spec.Parameter{}
- *param = *orig
- }
- }
- if r := w.walkRefCallback(¶m.Ref); r != ¶m.Ref {
- clone()
- param.Ref = *r
- }
- if s := w.walkSchema(param.Schema); s != param.Schema {
- clone()
- param.Schema = s
- }
- if param.Items != nil {
- if r := w.walkRefCallback(¶m.Items.Ref); r != ¶m.Items.Ref {
- param.Items.Ref = *r
- }
- }
- return param
- }
- func (w *mutatingReferenceWalker) walkParameters(params []spec.Parameter) ([]spec.Parameter, bool) {
- if params == nil {
- return nil, false
- }
- orig := params
- cloned := false
- clone := func() {
- if !cloned {
- cloned = true
- params = make([]spec.Parameter, len(params))
- copy(params, orig)
- }
- }
- for i := range params {
- if s := w.walkParameter(¶ms[i]); s != ¶ms[i] {
- clone()
- params[i] = *s
- }
- }
- return params, cloned
- }
- func (w *mutatingReferenceWalker) walkResponse(resp *spec.Response) *spec.Response {
- if resp == nil {
- return nil
- }
- orig := resp
- cloned := false
- clone := func() {
- if !cloned {
- cloned = true
- resp = &spec.Response{}
- *resp = *orig
- }
- }
- if r := w.walkRefCallback(&resp.Ref); r != &resp.Ref {
- clone()
- resp.Ref = *r
- }
- if s := w.walkSchema(resp.Schema); s != resp.Schema {
- clone()
- resp.Schema = s
- }
- return resp
- }
- func (w *mutatingReferenceWalker) walkResponses(resps *spec.Responses) *spec.Responses {
- if resps == nil {
- return nil
- }
- orig := resps
- cloned := false
- clone := func() {
- if !cloned {
- cloned = true
- resps = &spec.Responses{}
- *resps = *orig
- }
- }
- if r := w.walkResponse(resps.ResponsesProps.Default); r != resps.ResponsesProps.Default {
- clone()
- resps.Default = r
- }
- responsesCloned := false
- for k, v := range resps.ResponsesProps.StatusCodeResponses {
- if r := w.walkResponse(&v); r != &v {
- if !responsesCloned {
- responsesCloned = true
- clone()
- resps.ResponsesProps.StatusCodeResponses = make(map[int]spec.Response, len(orig.StatusCodeResponses))
- for k2, v2 := range orig.StatusCodeResponses {
- resps.ResponsesProps.StatusCodeResponses[k2] = v2
- }
- }
- resps.ResponsesProps.StatusCodeResponses[k] = *r
- }
- }
- return resps
- }
- func (w *mutatingReferenceWalker) walkOperation(op *spec.Operation) *spec.Operation {
- if op == nil {
- return nil
- }
- orig := op
- cloned := false
- clone := func() {
- if !cloned {
- cloned = true
- op = &spec.Operation{}
- *op = *orig
- }
- }
- parametersCloned := false
- for i := range op.Parameters {
- if s := w.walkParameter(&op.Parameters[i]); s != &op.Parameters[i] {
- if !parametersCloned {
- parametersCloned = true
- clone()
- op.Parameters = make([]spec.Parameter, len(orig.Parameters))
- copy(op.Parameters, orig.Parameters)
- }
- op.Parameters[i] = *s
- }
- }
- if r := w.walkResponses(op.Responses); r != op.Responses {
- clone()
- op.Responses = r
- }
- return op
- }
- func (w *mutatingReferenceWalker) walkPathItem(pathItem *spec.PathItem) *spec.PathItem {
- if pathItem == nil {
- return nil
- }
- orig := pathItem
- cloned := false
- clone := func() {
- if !cloned {
- cloned = true
- pathItem = &spec.PathItem{}
- *pathItem = *orig
- }
- }
- if p, changed := w.walkParameters(pathItem.Parameters); changed {
- clone()
- pathItem.Parameters = p
- }
- if op := w.walkOperation(pathItem.Get); op != pathItem.Get {
- clone()
- pathItem.Get = op
- }
- if op := w.walkOperation(pathItem.Head); op != pathItem.Head {
- clone()
- pathItem.Head = op
- }
- if op := w.walkOperation(pathItem.Delete); op != pathItem.Delete {
- clone()
- pathItem.Delete = op
- }
- if op := w.walkOperation(pathItem.Options); op != pathItem.Options {
- clone()
- pathItem.Options = op
- }
- if op := w.walkOperation(pathItem.Patch); op != pathItem.Patch {
- clone()
- pathItem.Patch = op
- }
- if op := w.walkOperation(pathItem.Post); op != pathItem.Post {
- clone()
- pathItem.Post = op
- }
- if op := w.walkOperation(pathItem.Put); op != pathItem.Put {
- clone()
- pathItem.Put = op
- }
- return pathItem
- }
- func (w *mutatingReferenceWalker) walkPaths(paths *spec.Paths) *spec.Paths {
- if paths == nil {
- return nil
- }
- orig := paths
- cloned := false
- clone := func() {
- if !cloned {
- cloned = true
- paths = &spec.Paths{}
- *paths = *orig
- }
- }
- pathsCloned := false
- for k, v := range paths.Paths {
- if p := w.walkPathItem(&v); p != &v {
- if !pathsCloned {
- pathsCloned = true
- clone()
- paths.Paths = make(map[string]spec.PathItem, len(orig.Paths))
- for k2, v2 := range orig.Paths {
- paths.Paths[k2] = v2
- }
- }
- paths.Paths[k] = *p
- }
- }
- return paths
- }
- func (w *mutatingReferenceWalker) Start(swagger *spec.Swagger) *spec.Swagger {
- if swagger == nil {
- return nil
- }
- orig := swagger
- cloned := false
- clone := func() {
- if !cloned {
- cloned = true
- swagger = &spec.Swagger{}
- *swagger = *orig
- }
- }
- parametersCloned := false
- for k, v := range swagger.Parameters {
- if p := w.walkParameter(&v); p != &v {
- if !parametersCloned {
- parametersCloned = true
- clone()
- swagger.Parameters = make(map[string]spec.Parameter, len(orig.Parameters))
- for k2, v2 := range orig.Parameters {
- swagger.Parameters[k2] = v2
- }
- }
- swagger.Parameters[k] = *p
- }
- }
- responsesCloned := false
- for k, v := range swagger.Responses {
- if r := w.walkResponse(&v); r != &v {
- if !responsesCloned {
- responsesCloned = true
- clone()
- swagger.Responses = make(map[string]spec.Response, len(orig.Responses))
- for k2, v2 := range orig.Responses {
- swagger.Responses[k2] = v2
- }
- }
- swagger.Responses[k] = *r
- }
- }
- definitionsCloned := false
- for k, v := range swagger.Definitions {
- if s := w.walkSchema(&v); s != &v {
- if !definitionsCloned {
- definitionsCloned = true
- clone()
- swagger.Definitions = make(spec.Definitions, len(orig.Definitions))
- for k2, v2 := range orig.Definitions {
- swagger.Definitions[k2] = v2
- }
- }
- swagger.Definitions[k] = *s
- }
- }
- if swagger.Paths != nil {
- if p := w.walkPaths(swagger.Paths); p != swagger.Paths {
- clone()
- swagger.Paths = p
- }
- }
- return swagger
- }
|