From 145b579e2bcd83f6d6eaae9c4d5b5840fc6ea8df Mon Sep 17 00:00:00 2001 From: Jatin Naik Date: Mon, 12 Aug 2024 23:33:53 +0100 Subject: [PATCH 1/6] fix: upgrade to latest kin-openapi --- collator.go | 12 +-- collator_test.go | 42 +++++----- document.go | 7 +- document_test.go | 4 +- go.mod | 28 +++---- go.sum | 60 ++++++------- include_headers.go | 5 +- include_headers_test.go | 10 +-- inliner.go | 41 ++++++++- internal/cmd/compiler_test.go | 2 +- internal/cmd/filter.go | 8 +- internal/cmd/filter_test.go | 10 +-- internal/cmd/resource.go | 8 +- internal/compiler/compiler_test.go | 2 +- internal/generator/functions.go | 2 +- internal/generator/generator_test.go | 6 +- internal/generator/resources.go | 3 +- internal/scraper/gcs_scraper_test.go | 4 +- internal/scraper/s3_scraper_test.go | 4 +- internal/scraper/scraper_test.go | 2 +- internal/simplebuild/build.go | 3 +- internal/simplebuild/build_test.go | 62 +++++++------- internal/simplebuild/refs_test.go | 23 ++--- internal/storage/collator.go | 8 +- internal/storage/collator_test.go | 20 +++-- merge.go | 9 +- merge_test.go | 22 ++--- ref_alias_resolver.go | 50 +++++------ ref_index.go | 84 +++++++++---------- remove_elements.go | 60 +++++-------- remove_elements_test.go | 49 +++++------ resource.go | 37 ++++++-- resource_versions.go | 4 +- spec.go | 7 +- spec_test.go | 2 +- .../.vervet/resource/version/index.ts.tmpl | 2 +- testdata/generators.yaml | 2 +- versionware/validator.go | 22 ++--- 38 files changed, 376 insertions(+), 350 deletions(-) diff --git a/collator.go b/collator.go index 162f7976..60c28128 100644 --- a/collator.go +++ b/collator.go @@ -268,11 +268,11 @@ func tagsEqual(x, y interface{}) bool { func (c *Collator) mergePaths(rv *ResourceVersion) error { if rv.T.Paths != nil && c.result.Paths == nil { - c.result.Paths = make(openapi3.Paths) + c.result.Paths = openapi3.NewPaths() } var errs error - for k, v := range rv.T.Paths { - for opName, opValue := range v.Operations() { + for k, v := range rv.T.Paths.Map() { + for opName, opValue := range rv.T.Paths.Value(k).Operations() { route := routeForPath(k, opName) if _, ok := c.seenRoutes[route]; ok { if c.useFirstRoute { @@ -285,13 +285,13 @@ func (c *Collator) mergePaths(rv *ResourceVersion) error { } } else { c.seenRoutes[route] = struct{}{} - if c.result.Paths[k] == nil { + if c.result.Paths.Value(k) == nil { // Path doesn't exist in output - c.result.Paths[k] = v + c.result.Paths.Set(k, v) } else { // There is another operation on this path, merge the // current operation into that one - c.result.Paths[k].SetOperation(opName, opValue) + c.result.Paths.Value(k).SetOperation(opName, opValue) } c.pathSources[k] = rv.path } diff --git a/collator_test.go b/collator_test.go index 3e09de30..d26fd257 100644 --- a/collator_test.go +++ b/collator_test.go @@ -13,7 +13,7 @@ func TestRefRemover(t *testing.T) { c := qt.New(t) doc, err := vervet.NewDocumentFile(testdata.Path("resources/projects/2021-08-20/spec.yaml")) c.Assert(err, qt.IsNil) - resp400 := doc.Paths["/orgs/{org_id}/projects/{project_id}"].Delete.Responses["400"] + resp400 := doc.Paths.Value("/orgs/{org_id}/projects/{project_id}").Delete.Responses.Status(400) errDoc := resp400.Value.Content["application/vnd.api+json"].Schema c.Assert(err, qt.IsNil) c.Assert("{\"$ref\":\"../errors.yaml#/ErrorDocument\"}", qt.JSONEquals, errDoc) @@ -62,8 +62,8 @@ func TestCollator(t *testing.T) { result := collator.Result() c.Assert( - result.Paths["/orgs/{orgId}/projects"]. - Get.Responses["200"]. + result.Paths.Value("/orgs/{orgId}/projects"). + Get.Responses.Status(200). Value. Content["application/vnd.api+json"]. Schema.Value.Properties["jsonapi"].Ref, @@ -71,9 +71,9 @@ func TestCollator(t *testing.T) { "#/components/schemas/JsonApi", ) schemaRef := result. - Paths["/examples/hello-world/{id}"]. + Paths.Value("/examples/hello-world/{id}"). Get. - Responses["200"]. + Responses.Status(200). Value. Content["application/vnd.api+json"]. Schema. @@ -86,9 +86,9 @@ func TestCollator(t *testing.T) { ":\"object\"}\n", qt.JSONEquals, schemaRef.Value) c.Assert(result.Components.Schemas["JsonApi"], qt.IsNotNil) - projectParameterRef := result.Paths["/orgs/{orgId}/projects"].Get.Parameters[0] + projectParameterRef := result.Paths.Value("/orgs/{orgId}/projects").Get.Parameters[0] c.Assert(projectParameterRef.Ref, qt.Equals, "#/components/parameters/Version") - exampleParameterRef := result.Paths["/examples/hello-world/{id}"].Get.Parameters[0] + exampleParameterRef := result.Paths.Value("/examples/hello-world/{id}").Get.Parameters[0] c.Assert(exampleParameterRef.Ref, qt.Equals, "") //nolint:lll // acked c.Assert("{\"description\":\"The requested version of the endpoint to process the request\",\"example\""+ @@ -96,13 +96,13 @@ func TestCollator(t *testing.T) { "\"Requested API version\",\"pattern\":\"^(wip|work-in-progress|experimental|beta|((([0-9]{4})-([0-1][0-9]))"+ "-((3[01])|(0[1-9])|([12][0-9]))(~(wip|work-in-progress|experimental|beta))?))$\",\"type\":\"string\"}}\n", qt.JSONEquals, exampleParameterRef.Value) - projectConflictRef := result.Paths["/orgs/{orgId}/projects"].Get.Parameters[6] - exampleConflictRef := result.Paths["/examples/hello-world/{id}"].Get.Parameters[3] + projectConflictRef := result.Paths.Value("/orgs/{orgId}/projects").Get.Parameters[6] + exampleConflictRef := result.Paths.Value("/examples/hello-world/{id}").Get.Parameters[3] c.Assert(projectConflictRef.Ref, qt.Not(qt.Equals), exampleConflictRef.Ref) - projectResp400Ref := result.Paths["/orgs/{orgId}/projects"].Get.Responses["400"] + projectResp400Ref := result.Paths.Value("/orgs/{orgId}/projects").Get.Responses.Status(400) c.Assert(projectResp400Ref.Ref, qt.Equals, "#/components/responses/400") - exampleResp400Ref := result.Paths["/examples/hello-world/{id}"].Get.Responses["400"] + exampleResp400Ref := result.Paths.Value("/examples/hello-world/{id}").Get.Responses.Status(400) c.Assert(exampleResp400Ref.Ref, qt.Equals, "") c.Assert("{\"content\":{\"application/vnd.api+json\":{\"schema\":{\"additionalProperties\":false,\"example\":{"+ "\"errors\":[{\"detail\":\"Permission denied for this resource\",\"status\":\"403\"}],\"jsonapi\":{\"version\":"+ @@ -168,11 +168,11 @@ func TestCollateUseFirstRoute(t *testing.T) { result := collator.Result() // First path chosen, route matching rules ignore path variable - c.Assert(result.Paths["/examples/hello-world/{id1}"], qt.Not(qt.IsNil)) - c.Assert(result.Paths["/examples/hello-world/{id2}"], qt.IsNil) + c.Assert(result.Paths.Value("/examples/hello-world/{id1}"), qt.Not(qt.IsNil)) + c.Assert(result.Paths.Value("/examples/hello-world/{id2}"), qt.IsNil) // First chosen path has description expected - c.Assert(result.Paths["/examples/hello-world/{id1}"].Get.Description, qt.Contains, " - from example 1") + c.Assert(result.Paths.Value("/examples/hello-world/{id1}").Get.Description, qt.Contains, " - from example 1") } func TestCollatePathConflict(t *testing.T) { @@ -215,7 +215,7 @@ func TestCollateMergingResources(t *testing.T) { c.Assert(err, qt.IsNil) result := collator.Result() - c.Assert(result.Paths["/orgs/{org_id}/projects/{project_id}"].Delete.Responses["204"], qt.IsNotNil) + c.Assert(result.Paths.Value("/orgs/{org_id}/projects/{project_id}").Delete.Responses.Status(204), qt.IsNotNil) } func TestCollateOperationsOnSamePath(t *testing.T) { @@ -238,10 +238,10 @@ func TestCollateOperationsOnSamePath(t *testing.T) { result := collator.Result() - c.Assert(result.Paths["/examples/hello-world"].Get, qt.Not(qt.IsNil)) - c.Assert(result.Paths["/examples/hello-world"].Get.Description, qt.Contains, " - from example 1") - c.Assert(result.Paths["/examples/hello-world"].Post, qt.Not(qt.IsNil)) - c.Assert(result.Paths["/examples/hello-world"].Post.Description, qt.Contains, " - from example 1") - c.Assert(result.Paths["/examples/hello-world"].Put, qt.Not(qt.IsNil)) - c.Assert(result.Paths["/examples/hello-world"].Put.Description, qt.Contains, " - from example 2") + c.Assert(result.Paths.Value("/examples/hello-world").Get, qt.Not(qt.IsNil)) + c.Assert(result.Paths.Value("/examples/hello-world").Get.Description, qt.Contains, " - from example 1") + c.Assert(result.Paths.Value("/examples/hello-world").Post, qt.Not(qt.IsNil)) + c.Assert(result.Paths.Value("/examples/hello-world").Post.Description, qt.Contains, " - from example 1") + c.Assert(result.Paths.Value("/examples/hello-world").Put, qt.Not(qt.IsNil)) + c.Assert(result.Paths.Value("/examples/hello-world").Put.Description, qt.Contains, " - from example 2") } diff --git a/document.go b/document.go index 266b0082..cf4060c4 100644 --- a/document.go +++ b/document.go @@ -70,18 +70,17 @@ func NewDocumentFile(specFile string) (_ *Document, returnErr error) { } var t openapi3.T + contents, err := os.ReadFile(specFile) if err != nil { return nil, err } + err = yaml.Unmarshal(contents, &t) if err != nil { return nil, err } - err = newRefAliasResolver(&t).resolve() - if err != nil { - return nil, err - } + newRefAliasResolver(&t).resolve() l := openapi3.NewLoader() l.IsExternalRefsAllowed = true diff --git a/document_test.go b/document_test.go index 4c346854..d59bbdf3 100644 --- a/document_test.go +++ b/document_test.go @@ -14,8 +14,8 @@ func TestNewDocumentFile(t *testing.T) { c := qt.New(t) doc, err := vervet.NewDocumentFile(testdata.Path("resources/_examples/hello-world/2021-06-01/spec.yaml")) c.Assert(err, qt.IsNil) - c.Assert(doc.Paths, qt.HasLen, 1) - c.Assert(doc.Paths["/examples/hello-world/{id}"], qt.Not(qt.IsNil)) + c.Assert(doc.Paths.Len(), qt.Equals, 1) + c.Assert(doc.Paths.Value("/examples/hello-world/{id}"), qt.Not(qt.IsNil)) c.Assert(doc.Components.Schemas["HelloWorld"], qt.Not(qt.IsNil)) c.Assert(doc.Validate(context.TODO()), qt.IsNil) } diff --git a/go.mod b/go.mod index 88406758..67ff2bbb 100644 --- a/go.mod +++ b/go.mod @@ -14,11 +14,11 @@ require ( github.com/dop251/goja v0.0.0-20231024180952-594410467bc6 github.com/elgohr/go-localstack v1.0.36 github.com/frankban/quicktest v1.14.6 - github.com/getkin/kin-openapi v0.120.0 + github.com/getkin/kin-openapi v0.127.0 github.com/ghodss/yaml v1.0.0 github.com/go-chi/chi/v5 v5.0.10 github.com/google/go-cmp v0.6.0 - github.com/google/uuid v1.4.0 + github.com/google/uuid v1.6.0 github.com/gorilla/mux v1.8.0 github.com/manifoldco/promptui v0.9.0 github.com/mitchellh/reflectwalk v1.0.2 @@ -34,8 +34,8 @@ require ( github.com/urfave/cli/v2 v2.25.7 github.com/vmware-labs/yaml-jsonpath v0.3.2 go.uber.org/multierr v1.11.0 - golang.org/x/exp v0.0.0-20231006140011-7918f672742d - golang.org/x/sync v0.4.0 + golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa + golang.org/x/sync v0.8.0 google.golang.org/api v0.149.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -80,8 +80,8 @@ require ( github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/go-ole/go-ole v1.2.6 // indirect - github.com/go-openapi/jsonpointer v0.20.0 // indirect - github.com/go-openapi/swag v0.22.4 // indirect + github.com/go-openapi/jsonpointer v0.21.0 // indirect + github.com/go-openapi/swag v0.23.0 // indirect github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect @@ -91,7 +91,7 @@ require ( github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect github.com/googleapis/gax-go/v2 v2.12.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/invopop/yaml v0.2.0 // indirect + github.com/invopop/yaml v0.3.1 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/klauspost/compress v1.17.1 // indirect @@ -121,7 +121,7 @@ require ( github.com/prometheus/common v0.45.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect github.com/rivo/uniseg v0.4.4 // indirect - github.com/rogpeppe/go-internal v1.11.0 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.3.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect @@ -138,13 +138,13 @@ require ( github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect go.opencensus.io v0.24.0 // indirect - golang.org/x/crypto v0.22.0 // indirect - golang.org/x/mod v0.13.0 // indirect - golang.org/x/net v0.24.0 // indirect + golang.org/x/crypto v0.26.0 // indirect + golang.org/x/mod v0.20.0 // indirect + golang.org/x/net v0.28.0 // indirect golang.org/x/oauth2 v0.13.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect - golang.org/x/tools v0.14.0 // indirect + golang.org/x/sys v0.23.0 // indirect + golang.org/x/text v0.17.0 // indirect + golang.org/x/tools v0.24.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b // indirect diff --git a/go.sum b/go.sum index f5b719f6..fa895389 100644 --- a/go.sum +++ b/go.sum @@ -190,8 +190,8 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/getkin/kin-openapi v0.120.0 h1:MqJcNJFrMDFNc07iwE8iFC5eT2k/NPUFDIpNeiZv8Jg= -github.com/getkin/kin-openapi v0.120.0/go.mod h1:PCWw/lfBrJY4HcdqE3jj+QFkaFK8ABoqo7PvqVhXXqw= +github.com/getkin/kin-openapi v0.127.0 h1:Mghqi3Dhryf3F8vR370nN67pAERW+3a95vomb3MAREY= +github.com/getkin/kin-openapi v0.127.0/go.mod h1:OZrfXzUfGrNbsKj+xmFBx6E5c6yH3At/tAKSc2UszXM= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk= @@ -201,10 +201,10 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ= -github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA= -github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= -github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= @@ -287,8 +287,8 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4 github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= -github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= @@ -306,8 +306,8 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= -github.com/invopop/yaml v0.2.0 h1:7zky/qH+O0DwAyoobXUqvVBwgBFRxKoQ/3FjcVpjTMY= -github.com/invopop/yaml v0.2.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q= +github.com/invopop/yaml v0.3.1 h1:f0+ZpmhfBSS4MhG+4HYseMdJhoeeopbSKbq5Rpeelso= +github.com/invopop/yaml v0.3.1/go.mod h1:PMOp3nn4/12yEZUFfmOuNHJsZToEEOwoWsT+D81KkeA= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= @@ -423,8 +423,8 @@ github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUc github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A= github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= @@ -477,8 +477,9 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= @@ -524,8 +525,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= -golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= +golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -536,8 +537,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= -golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= +golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa h1:ELnwvuAXPNtPk1TJRuGkI9fDTwym6AYBu0qzT8AcHdI= +golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -562,8 +563,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= -golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -602,8 +603,8 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -626,8 +627,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= -golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -690,8 +691,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= +golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -703,8 +704,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -761,8 +762,8 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= -golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -893,7 +894,6 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20191026110619-0b21df46bc1d/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= diff --git a/include_headers.go b/include_headers.go index 0e6029ef..b760f13b 100644 --- a/include_headers.go +++ b/include_headers.go @@ -32,7 +32,8 @@ type includeHeaders struct { } func (w *includeHeaders) apply() error { - for _, pathItem := range w.doc.Paths { + for _, path := range w.doc.Paths.InMatchingOrder() { + pathItem := w.doc.Paths.Value(path) if err := w.applyOperation(pathItem.Connect); err != nil { return err } @@ -65,7 +66,7 @@ func (w *includeHeaders) applyOperation(op *openapi3.Operation) error { if op == nil { return nil // nothing to do } - for _, respRef := range op.Responses { + for _, respRef := range op.Responses.Map() { resp := respRef.Value headersContents, ok := resp.Extensions[ExtSnykIncludeHeaders].(map[string]interface{}) if !ok { diff --git a/include_headers_test.go b/include_headers_test.go index 77888258..a6534fa0 100644 --- a/include_headers_test.go +++ b/include_headers_test.go @@ -19,9 +19,9 @@ func TestCommonResponseHeaders(t *testing.T) { c.Assert(err, qt.IsNil) // Headers are not included - pathItem := doc.Paths["/examples/hello-world"] + pathItem := doc.Paths.Value("/examples/hello-world") c.Assert(pathItem, qt.Not(qt.IsNil)) - resp := pathItem.Post.Responses["201"].Value + resp := pathItem.Post.Responses.Status(201).Value c.Assert(resp, qt.Not(qt.IsNil)) // There's a Location header defined outside of the common includes c.Assert(resp.Headers, qt.HasLen, 1) @@ -30,14 +30,14 @@ func TestCommonResponseHeaders(t *testing.T) { c.Assert(err, qt.IsNil) // Included header refs are resolved - pathItem = doc.Paths["/examples/hello-world"] + pathItem = doc.Paths.Value("/examples/hello-world") c.Assert(pathItem, qt.Not(qt.IsNil)) - resp = pathItem.Post.Responses["201"].Value + resp = pathItem.Post.Responses.Status(201).Value c.Assert(resp, qt.Not(qt.IsNil)) // Now add 3 more common included headers c.Assert(resp.Headers, qt.HasLen, 4) for _, name := range []string{"snyk-version-requested", "snyk-version-served", "snyk-request-id"} { // All of these headers are string type - c.Assert(resp.Headers[name].Value.Schema.Value.Type, qt.Equals, "string") + c.Assert(resp.Headers[name].Value.Schema.Value.Type.Is("string"), qt.IsTrue) } } diff --git a/inliner.go b/inliner.go index ce606d5c..37ae9a91 100644 --- a/inliner.go +++ b/inliner.go @@ -25,7 +25,46 @@ func (in *Inliner) AddRef(ref string) { // Inline inlines all the JSON References previously indicated with AddRef in // the given OpenAPI document. func (in *Inliner) Inline(doc *openapi3.T) error { - return reflectwalk.Walk(doc, in) + for _, path := range doc.Paths.InMatchingOrder() { + for _, operation := range doc.Paths.Value(path).Operations() { + for _, parameter := range operation.Parameters { + parameter.Ref = in.removeIfMatched(parameter.Ref) + in.checkSchemaRef(parameter.Value.Schema) + for _, exampleRef := range parameter.Value.Examples { + exampleRef.Ref = in.removeIfMatched(exampleRef.Ref) + } + } + if operation.RequestBody != nil { + operation.RequestBody.Ref = in.removeIfMatched(operation.RequestBody.Ref) + } + for _, response := range operation.Responses.Map() { + response.Ref = in.removeIfMatched(response.Ref) + if response.Value != nil { + for _, mediaType := range response.Value.Content { + in.checkSchemaRef(mediaType.Schema) + for _, example := range mediaType.Examples { + example.Ref = in.removeIfMatched(example.Ref) + } + } + } + } + } + + } + return nil +} + +func (in *Inliner) checkSchemaRef(schema *openapi3.SchemaRef) { + schema.Ref = in.removeIfMatched(schema.Ref) + for _, properties := range schema.Value.Properties { + properties.Ref = in.removeIfMatched(properties.Ref) + } +} +func (in *Inliner) removeIfMatched(ref string) string { + if _, match := in.refs[ref]; match { + return "" + } + return ref } // Struct implements reflectwalk.StructWalker. diff --git a/internal/cmd/compiler_test.go b/internal/cmd/compiler_test.go index 7ddd6c37..74eb48ee 100644 --- a/internal/cmd/compiler_test.go +++ b/internal/cmd/compiler_test.go @@ -42,7 +42,7 @@ func TestBuild(t *testing.T) { c.Assert(err, qt.IsNil) c.Assert(doc.Validate(context.TODO()), qt.IsNil) for _, path := range test.paths { - c.Assert(doc.Paths[path], qt.Not(qt.IsNil)) + c.Assert(doc.Paths.Value(path), qt.Not(qt.IsNil)) } }) } diff --git a/internal/cmd/filter.go b/internal/cmd/filter.go index 9dd0b420..e2b5cec7 100644 --- a/internal/cmd/filter.go +++ b/internal/cmd/filter.go @@ -43,14 +43,14 @@ func Filter(ctx *cli.Context) error { if excludePaths := ctx.StringSlice("exclude-paths"); len(excludePaths) > 0 { for _, excludePath := range excludePaths { - delete(doc.Paths, excludePath) + doc.Paths.Delete(excludePath) } } if includePaths := ctx.StringSlice("include-paths"); len(includePaths) > 0 { - newPaths := openapi3.Paths{} + newPaths := openapi3.NewPaths() for _, includePath := range includePaths { - if pathInfo, ok := doc.Paths[includePath]; ok { - newPaths[includePath] = pathInfo + if pathInfo := doc.Paths.Value(includePath); pathInfo != nil { + newPaths.Set(includePath, pathInfo) } } doc.Paths = newPaths diff --git a/internal/cmd/filter_test.go b/internal/cmd/filter_test.go index 6f46996a..719ad984 100644 --- a/internal/cmd/filter_test.go +++ b/internal/cmd/filter_test.go @@ -40,11 +40,11 @@ func TestFilterInclude(t *testing.T) { c.Assert(err, qt.IsNil) // Included paths and their referenced components are present - c.Assert(doc.Paths["/examples/hello-world/{id}"], qt.Not(qt.IsNil)) + c.Assert(doc.Paths.Value("/examples/hello-world/{id}"), qt.Not(qt.IsNil)) c.Assert(doc.Components.Schemas["HelloWorld"], qt.Not(qt.IsNil)) // Not-included paths are not present - c.Assert(doc.Paths["/openapi"], qt.IsNil) + c.Assert(doc.Paths.Value("/openapi"), qt.IsNil) } func XestFilterExclude(t *testing.T) { @@ -78,11 +78,11 @@ func XestFilterExclude(t *testing.T) { c.Assert(err, qt.IsNil) // Excluded paths and components only these reference, are not present - c.Assert(doc.Paths["/examples/hello-world/{id}"], qt.IsNil) + c.Assert(doc.Paths.Value("/examples/hello-world/{id}"), qt.IsNil) c.Assert(doc.Components.Schemas["HelloWorld"], qt.IsNil) // Not-excluded paths and referenced components are present - c.Assert(doc.Paths["/openapi"], qt.Not(qt.IsNil)) - c.Assert(doc.Paths["/openapi/{version}"], qt.Not(qt.IsNil)) + c.Assert(doc.Paths.Value("/openapi"), qt.Not(qt.IsNil)) + c.Assert(doc.Paths.Value("/openapi/{version}"), qt.Not(qt.IsNil)) c.Assert(doc.Components.Headers["VersionRequestedResponseHeader"], qt.Not(qt.IsNil)) } diff --git a/internal/cmd/resource.go b/internal/cmd/resource.go index fe0cd570..b2c049f7 100644 --- a/internal/cmd/resource.go +++ b/internal/cmd/resource.go @@ -82,13 +82,11 @@ func ResourceShow(ctx *cli.Context) error { if rcArg := ctx.Args().Get(1); rcArg != "" && rcArg != rc.Name { continue } - var pathNames []string - for k := range rc.Paths { - pathNames = append(pathNames, k) - } + + pathNames := rc.Paths.InMatchingOrder() sort.Strings(pathNames) for _, pathName := range pathNames { - pathSpec := rc.Paths[pathName] + pathSpec := rc.Paths.Value(pathName) if pathSpec.Get != nil { table.Append([]string{apiName, rc.Name, version.String(), pathName, "GET", pathSpec.Get.OperationID}) } diff --git a/internal/compiler/compiler_test.go b/internal/compiler/compiler_test.go index e82eff2b..e62f1e2a 100644 --- a/internal/compiler/compiler_test.go +++ b/internal/compiler/compiler_test.go @@ -96,7 +96,7 @@ func TestCompilerSmoke(t *testing.T) { c.Assert(restApi.resources, qt.HasLen, 1) c.Assert(restApi.resources[0].sourceFiles, qt.Contains, "testdata/resources/projects/2021-06-04/spec.yaml") c.Assert(restApi.overlayIncludes, qt.HasLen, 1) - c.Assert(restApi.overlayIncludes[0].Paths, qt.HasLen, 2) + c.Assert(restApi.overlayIncludes[0].Paths.Len(), qt.Equals, 2) c.Assert( restApi.overlayInlines[0].Servers[0].URL, qt.Contains, diff --git a/internal/generator/functions.go b/internal/generator/functions.go index 625af205..a7f69bea 100644 --- a/internal/generator/functions.go +++ b/internal/generator/functions.go @@ -58,7 +58,7 @@ var ( }, "isAssociativeArray": func(s *openapi3.Schema) bool { return s != nil && - s.Type == "object" && + s.Type.Is("object") && len(s.Properties) == 0 && s.AdditionalProperties.Has != nil && *s.AdditionalProperties.Has diff --git a/internal/generator/generator_test.go b/internal/generator/generator_test.go index eb19b733..34b1bd65 100644 --- a/internal/generator/generator_test.go +++ b/internal/generator/generator_test.go @@ -260,11 +260,11 @@ function tsType(oasType) { [key: string]: object; } -{{- else if eq .Type "object" }}{ +{{- else if .Type.Is "object" }}{ {{- include "interfaceProperties" . | indent 2 }} } -{{- else if eq .Type "array" }}Array<{{ template "resolveSchemaRef" .Items }}> +{{- else if .Type.Is "array" }}Array<{{ template "resolveSchemaRef" .Items }}> {{- else }}{{ .Type | tsType }} @@ -282,7 +282,7 @@ function tsType(oasType) { {{- if isAssociativeArray .Schema.Value }} export interface {{ .Name }} {{ template "schemaTypeDef" .Schema.Value }}; -{{- else if eq .Schema.Value.Type "object" }} +{{- else if .Schema.Value.Type.Is "object" }} export interface {{ .Name }} {{ template "schemaTypeDef" .Schema.Value }}; {{- else }} diff --git a/internal/generator/resources.go b/internal/generator/resources.go index 0de2eeab..b0fd9553 100644 --- a/internal/generator/resources.go +++ b/internal/generator/resources.go @@ -43,7 +43,8 @@ func MapResourceOperations(resourceVersions *vervet.ResourceVersions) (Operation if err != nil { return nil, err } - for path, pathItem := range r.Document.Paths { + for _, path := range r.Document.Paths.InMatchingOrder() { + pathItem := r.Document.Paths.Value(path) ops := MapPathOperations(pathItem) for method, op := range ops { opVersion := OperationVersion{ diff --git a/internal/scraper/gcs_scraper_test.go b/internal/scraper/gcs_scraper_test.go index 8c63a905..1732c8d1 100644 --- a/internal/scraper/gcs_scraper_test.go +++ b/internal/scraper/gcs_scraper_test.go @@ -76,7 +76,7 @@ func TestGCSScraper(t *testing.T) { spec, err := l.LoadFromData(specData) c.Assert(err, qt.IsNil) c.Assert(spec, qt.IsNotNil) - c.Assert(len(spec.Paths), qt.Equals, collatedPaths[version.String()]) + c.Assert(spec.Paths.Len(), qt.Equals, collatedPaths[version.String()]) } } @@ -140,6 +140,6 @@ func TestGCSScraperCollation(t *testing.T) { spec, err := l.LoadFromData(specData) c.Assert(err, qt.IsNil) c.Assert(spec, qt.IsNotNil) - c.Assert(len(spec.Paths), qt.Equals, collatedPaths[version.String()]) + c.Assert(spec.Paths.Len(), qt.Equals, collatedPaths[version.String()]) } } diff --git a/internal/scraper/s3_scraper_test.go b/internal/scraper/s3_scraper_test.go index 32c82ace..a9407081 100644 --- a/internal/scraper/s3_scraper_test.go +++ b/internal/scraper/s3_scraper_test.go @@ -72,7 +72,7 @@ func TestS3Scraper(t *testing.T) { spec, err := l.LoadFromData(specData) c.Assert(err, qt.IsNil) c.Assert(spec, qt.IsNotNil) - c.Assert(len(spec.Paths), qt.Equals, collatedPaths[version.String()]) + c.Assert(spec.Paths.Len(), qt.Equals, collatedPaths[version.String()]) } } @@ -132,6 +132,6 @@ func TestS3ScraperCollation(t *testing.T) { spec, err := l.LoadFromData(specData) c.Assert(err, qt.IsNil) c.Assert(spec, qt.IsNotNil) - c.Assert(len(spec.Paths), qt.Equals, collatedPaths[version.String()]) + c.Assert(spec.Paths.Len(), qt.Equals, collatedPaths[version.String()]) } } diff --git a/internal/scraper/scraper_test.go b/internal/scraper/scraper_test.go index c326218b..f79b3a25 100644 --- a/internal/scraper/scraper_test.go +++ b/internal/scraper/scraper_test.go @@ -141,7 +141,7 @@ func TestScraper(t *testing.T) { spec, err := l.LoadFromData(specData) c.Assert(err, qt.IsNil) c.Assert(spec, qt.IsNotNil) - c.Assert(len(spec.Paths), qt.Equals, collatedPaths[version.String()]) + c.Assert(spec.Paths.Len(), qt.Equals, collatedPaths[version.String()]) } } diff --git a/internal/simplebuild/build.go b/internal/simplebuild/build.go index f058b497..79674f4f 100644 --- a/internal/simplebuild/build.go +++ b/internal/simplebuild/build.go @@ -157,7 +157,8 @@ func LoadPaths(ctx context.Context, api *config.API) (Operations, error) { return nil, fmt.Errorf("failed to localize refs: %w", err) } - for pathName, pathDef := range doc.T.Paths { + for _, pathName := range doc.T.Paths.InMatchingOrder() { + pathDef := doc.T.Paths.Value(pathName) for opName, opDef := range pathDef.Operations() { k := OpKey{ Path: pathName, diff --git a/internal/simplebuild/build_test.go b/internal/simplebuild/build_test.go index 6f68031f..083853b7 100644 --- a/internal/simplebuild/build_test.go +++ b/internal/simplebuild/build_test.go @@ -107,7 +107,7 @@ func TestBuild(t *testing.T) { output, err := ops.Build(vervet.MustParseVersion("2024-01-01")) c.Assert(err, qt.IsNil) c.Assert(output[0].VersionDate, qt.Equals, time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC)) - c.Assert(output[0].Doc.Paths["/foo"].Get, qt.IsNotNil) + c.Assert(output[0].Doc.Paths.Value("/foo").Get, qt.IsNotNil) }) c.Run("merges operations from the same version", func(c *qt.C) { @@ -146,9 +146,9 @@ func TestBuild(t *testing.T) { output, err := ops.Build(vervet.MustParseVersion("2024-01-01")) c.Assert(err, qt.IsNil) c.Assert(output[0].VersionDate, qt.Equals, version.Date) - c.Assert(output[0].Doc.Paths["/foo"].Get, qt.Equals, getFoo) - c.Assert(output[0].Doc.Paths["/foo"].Post, qt.Equals, postFoo) - c.Assert(output[0].Doc.Paths["/bar"].Get, qt.Equals, getBar) + c.Assert(output[0].Doc.Paths.Value("/foo").Get, qt.Equals, getFoo) + c.Assert(output[0].Doc.Paths.Value("/foo").Post, qt.Equals, postFoo) + c.Assert(output[0].Doc.Paths.Value("/bar").Get, qt.Equals, getBar) }) c.Run("generates an output per unique version", func(c *qt.C) { @@ -238,19 +238,19 @@ func TestBuild(t *testing.T) { slices.SortFunc(output, compareDocs) c.Assert(output[0].VersionDate, qt.Equals, versionA.Date) - c.Assert(output[0].Doc.Paths["/foo"].Get, qt.Equals, getFoo) - c.Assert(output[0].Doc.Paths["/foo"].Post, qt.IsNil) - c.Assert(output[0].Doc.Paths["/bar"], qt.IsNil) + c.Assert(output[0].Doc.Paths.Value("/foo").Get, qt.Equals, getFoo) + c.Assert(output[0].Doc.Paths.Value("/foo").Post, qt.IsNil) + c.Assert(output[0].Doc.Paths.Value("/bar"), qt.IsNil) c.Assert(output[1].VersionDate, qt.Equals, versionB.Date) - c.Assert(output[1].Doc.Paths["/foo"].Get, qt.Equals, getFoo) - c.Assert(output[1].Doc.Paths["/foo"].Post, qt.Equals, postFoo) - c.Assert(output[1].Doc.Paths["/bar"], qt.IsNil) + c.Assert(output[1].Doc.Paths.Value("/foo").Get, qt.Equals, getFoo) + c.Assert(output[1].Doc.Paths.Value("/foo").Post, qt.Equals, postFoo) + c.Assert(output[1].Doc.Paths.Value("/bar"), qt.IsNil) c.Assert(output[2].VersionDate, qt.Equals, versionC.Date) - c.Assert(output[2].Doc.Paths["/foo"].Get, qt.Equals, getFoo) - c.Assert(output[2].Doc.Paths["/foo"].Post, qt.Equals, postFoo) - c.Assert(output[2].Doc.Paths["/bar"].Get, qt.Equals, getBar) + c.Assert(output[2].Doc.Paths.Value("/foo").Get, qt.Equals, getFoo) + c.Assert(output[2].Doc.Paths.Value("/foo").Post, qt.Equals, postFoo) + c.Assert(output[2].Doc.Paths.Value("/bar").Get, qt.Equals, getBar) }) c.Run("resolves operations to latest version with respect to output", func(c *qt.C) { @@ -289,16 +289,16 @@ func TestBuild(t *testing.T) { slices.SortFunc(output, compareDocs) c.Assert(output[0].VersionDate, qt.Equals, versionA.Date) - c.Assert(output[0].Doc.Paths["/foo"].Get, qt.Equals, getFooOld) - c.Assert(output[0].Doc.Paths["/bar"], qt.IsNil) + c.Assert(output[0].Doc.Paths.Value("/foo").Get, qt.Equals, getFooOld) + c.Assert(output[0].Doc.Paths.Value("/bar"), qt.IsNil) c.Assert(output[1].VersionDate, qt.Equals, versionB.Date) - c.Assert(output[1].Doc.Paths["/foo"].Get, qt.Equals, getFooOld) - c.Assert(output[1].Doc.Paths["/bar"].Get, qt.Equals, getBar) + c.Assert(output[1].Doc.Paths.Value("/foo").Get, qt.Equals, getFooOld) + c.Assert(output[1].Doc.Paths.Value("/bar").Get, qt.Equals, getBar) c.Assert(output[2].VersionDate, qt.Equals, versionC.Date) - c.Assert(output[2].Doc.Paths["/foo"].Get, qt.Equals, getFooNew) - c.Assert(output[2].Doc.Paths["/bar"].Get, qt.Equals, getBar) + c.Assert(output[2].Doc.Paths.Value("/foo").Get, qt.Equals, getFooNew) + c.Assert(output[2].Doc.Paths.Value("/bar").Get, qt.Equals, getBar) }) c.Run("does not generate versions before pivot date", func(c *qt.C) { @@ -339,12 +339,12 @@ func TestBuild(t *testing.T) { c.Assert(len(output), qt.Equals, 2) c.Assert(output[0].VersionDate, qt.Equals, versionB.Date) - c.Assert(output[0].Doc.Paths["/foo"].Get, qt.Equals, getFooOld) - c.Assert(output[0].Doc.Paths["/bar"].Get, qt.Equals, getBar) + c.Assert(output[0].Doc.Paths.Value("/foo").Get, qt.Equals, getFooOld) + c.Assert(output[0].Doc.Paths.Value("/bar").Get, qt.Equals, getBar) c.Assert(output[1].VersionDate, qt.Equals, versionC.Date) - c.Assert(output[1].Doc.Paths["/foo"].Get, qt.Equals, getFooNew) - c.Assert(output[1].Doc.Paths["/bar"].Get, qt.Equals, getBar) + c.Assert(output[1].Doc.Paths.Value("/foo").Get, qt.Equals, getFooNew) + c.Assert(output[1].Doc.Paths.Value("/bar").Get, qt.Equals, getBar) }) c.Run("lower stabilities are merged into higher", func(c *qt.C) { @@ -388,18 +388,18 @@ func TestBuild(t *testing.T) { slices.SortFunc(output, compareDocs) c.Assert(output[0].VersionDate, qt.Equals, versionBetaA.Date) - c.Assert(output[0].Doc.Paths["/foo"], qt.IsNil) - c.Assert(output[0].Doc.Paths["/bar"].Get, qt.Equals, getBar) + c.Assert(output[0].Doc.Paths.Value("/foo"), qt.IsNil) + c.Assert(output[0].Doc.Paths.Value("/bar").Get, qt.Equals, getBar) c.Assert(output[1].VersionDate, qt.Equals, versionGA.Date) - c.Assert(output[1].Doc.Paths["/foo"].Get, qt.Equals, getFoo) - c.Assert(output[1].Doc.Paths["/foo"].Post, qt.IsNil) - c.Assert(output[0].Doc.Paths["/bar"].Get, qt.Equals, getBar) + c.Assert(output[1].Doc.Paths.Value("/foo").Get, qt.Equals, getFoo) + c.Assert(output[1].Doc.Paths.Value("/foo").Post, qt.IsNil) + c.Assert(output[0].Doc.Paths.Value("/bar").Get, qt.Equals, getBar) c.Assert(output[2].VersionDate, qt.Equals, versionBetaB.Date) - c.Assert(output[2].Doc.Paths["/foo"].Get, qt.Equals, getFoo) - c.Assert(output[2].Doc.Paths["/foo"].Post, qt.Equals, postFoo) - c.Assert(output[2].Doc.Paths["/bar"].Get, qt.Equals, getBar) + c.Assert(output[2].Doc.Paths.Value("/foo").Get, qt.Equals, getFoo) + c.Assert(output[2].Doc.Paths.Value("/foo").Post, qt.Equals, postFoo) + c.Assert(output[2].Doc.Paths.Value("/bar").Get, qt.Equals, getBar) }) } diff --git a/internal/simplebuild/refs_test.go b/internal/simplebuild/refs_test.go index 2ebade08..226ec114 100644 --- a/internal/simplebuild/refs_test.go +++ b/internal/simplebuild/refs_test.go @@ -21,9 +21,7 @@ func TestResolveRefs(t *testing.T) { }}, } doc := openapi3.T{ - Paths: openapi3.Paths{ - "/foo": &path, - }, + Paths: openapi3.NewPaths(openapi3.WithPath("/foo", &path)), } rr := simplebuild.NewRefResolver(&doc) @@ -48,10 +46,7 @@ func TestResolveRefs(t *testing.T) { }}, } doc := openapi3.T{ - Paths: openapi3.Paths{ - "/foo": &pathA, - "/bar": &pathB, - }, + Paths: openapi3.NewPaths(openapi3.WithPath("/foo", &pathA), openapi3.WithPath("/bar", &pathB)), } rr := simplebuild.NewRefResolver(&doc) @@ -77,10 +72,8 @@ func TestResolveRefs(t *testing.T) { }}, } doc := openapi3.T{ - Paths: openapi3.Paths{ - "/foo": &pathA, - "/bar": &pathB, - }, + + Paths: openapi3.NewPaths(openapi3.WithPath("/foo", &pathA), openapi3.WithPath("/bar", &pathB)), } rr := simplebuild.NewRefResolver(&doc) @@ -108,9 +101,7 @@ func TestResolveRefs(t *testing.T) { }}, } doc := openapi3.T{ - Paths: openapi3.Paths{ - "/foo": &path, - }, + Paths: openapi3.NewPaths(openapi3.WithPath("/foo", &path)), } rr := simplebuild.NewRefResolver(&doc) @@ -130,9 +121,7 @@ func TestResolveRefs(t *testing.T) { } doc := openapi3.T{ Components: &openapi3.Components{}, - Paths: openapi3.Paths{ - "/foo": &path, - }, + Paths: openapi3.NewPaths(openapi3.WithPath("/foo", &path)), } rr := simplebuild.NewRefResolver(&doc) diff --git a/internal/storage/collator.go b/internal/storage/collator.go index 5df1fbae..d0ac31ed 100644 --- a/internal/storage/collator.go +++ b/internal/storage/collator.go @@ -164,13 +164,13 @@ func mergeRevisions(revisions ContentRevisions) (*openapi3.T, error) { // first instances of these paths and remove them from subsequent specs // to prevent failing the collate on conflicting paths. if haveOpenAPI { - delete(src.Paths, "/openapi") - } else if _, ok := src.Paths["/openapi"]; ok { + src.Paths.Delete("/openapi") + } else if pathItem := src.Paths.Value("/openapi"); pathItem != nil { haveOpenAPI = true } if haveOpenAPIVersion { - delete(src.Paths, "/openapi/{version}") - } else if _, ok := src.Paths["/openapi/{version}"]; ok { + src.Paths.Delete("/openapi/{version}") + } else if pathItem := src.Paths.Value("/openapi/{version}"); pathItem != nil { haveOpenAPIVersion = true } diff --git a/internal/storage/collator_test.go b/internal/storage/collator_test.go index 9d31ddf3..05634bd1 100644 --- a/internal/storage/collator_test.go +++ b/internal/storage/collator_test.go @@ -150,8 +150,9 @@ func TestCollator_Collate(t *testing.T) { c.Assert(specs[v20220401_ga].Paths.Find("/example"), qt.IsNotNil) // No filtering, so extensions are all present - c.Assert(specs[v20220401_ga].Paths["/example"].Post.Extensions["x-other-internal"], qt.Not(qt.IsNil)) - c.Assert(specs[v20220401_ga].Paths["/example"].Post.Responses["204"].Value.Extensions["x-internal"], qt.Not(qt.IsNil)) + c.Assert(specs[v20220401_ga].Paths.Value("/example").Post.Extensions["x-other-internal"], qt.Not(qt.IsNil)) + c.Assert(specs[v20220401_ga].Paths.Value("/example").Post. + Responses.Status(204).Value.Extensions["x-internal"], qt.Not(qt.IsNil)) } func TestCollator_Collate_MigratingEndpoints(t *testing.T) { @@ -183,11 +184,11 @@ func TestCollator_Collate_MigratingEndpoints(t *testing.T) { c.Assert(specs[v20220201_exp].Paths.Find("/test"), qt.IsNotNil) c.Assert(specs[v20230314_exp].Paths.Find("/test"), qt.IsNotNil) - c.Assert(specs[v20220201_exp].Paths["/test"].Get.Responses["204"], qt.IsNotNil) - c.Assert(specs[v20220201_exp].Paths["/test"].Get.Responses["200"], qt.IsNil) + c.Assert(specs[v20220201_exp].Paths.Value("/test").Get.Responses.Status(204), qt.IsNotNil) + c.Assert(specs[v20220201_exp].Paths.Value("/test").Get.Responses.Status(200), qt.IsNil) - c.Assert(specs[v20230314_exp].Paths["/test"].Get.Responses["200"], qt.IsNotNil) - c.Assert(specs[v20230314_exp].Paths["/test"].Get.Responses["204"], qt.IsNil) + c.Assert(specs[v20230314_exp].Paths.Value("/test").Get.Responses.Status(200), qt.IsNotNil) + c.Assert(specs[v20230314_exp].Paths.Value("/test").Get.Responses.Status(204), qt.IsNil) } func TestCollator_Collate_ExcludePatterns(t *testing.T) { @@ -218,8 +219,9 @@ func TestCollator_Collate_ExcludePatterns(t *testing.T) { specs, err := collator.Collate() c.Assert(err, qt.IsNil) - c.Assert(specs[v20220401_ga].Paths["/example"].Post.Extensions["x-other-internal"], qt.IsNil) - c.Assert(specs[v20220401_ga].Paths["/example"].Post.Responses["204"].Value.Extensions["x-internal"], qt.IsNil) + c.Assert(specs[v20220401_ga].Paths.Value("/example").Post.Extensions["x-other-internal"], qt.IsNil) + c.Assert(specs[v20220401_ga].Paths.Value("/example").Post. + Responses.Status(204).Value.Extensions["x-internal"], qt.IsNil) } func TestCollator_Collate_Conflict(t *testing.T) { @@ -252,7 +254,7 @@ func TestCollator_Collate_Conflict(t *testing.T) { specs, err := collator.Collate() c.Assert(err, qt.IsNil) // First path wins - c.Assert(specs[vervet.MustParseVersion("2021-06-15")].Paths["/examples/hello-world"].Post.Description, + c.Assert(specs[vervet.MustParseVersion("2021-06-15")].Paths.Value("/examples/hello-world").Post.Description, qt.Equals, "Create a single result from the hello-world example - from example 1") } diff --git a/merge.go b/merge.go index 1c3e238e..536e504d 100644 --- a/merge.go +++ b/merge.go @@ -177,11 +177,12 @@ func mergeInfo(dst, src *openapi3.T, replace bool) { func mergePaths(dst, src *openapi3.T, replace bool) { if src.Paths != nil && dst.Paths == nil { - dst.Paths = make(openapi3.Paths, len(src.Paths)) + dst.Paths = openapi3.NewPathsWithCapacity(src.Paths.Len()) } - for k, v := range src.Paths { - if _, ok := dst.Paths[k]; !ok || replace { - dst.Paths[k] = v + for _, key := range src.Paths.InMatchingOrder() { + v := src.Paths.Value(key) + if pathItem := dst.Paths.Value(key); pathItem == nil || replace { + dst.Paths.Set(key, v) } } } diff --git a/merge_test.go b/merge_test.go index 3f6d7730..7fcb7ec4 100644 --- a/merge_test.go +++ b/merge_test.go @@ -159,15 +159,12 @@ tags: err := vervet.Merge(dst, src, false) c.Assert(err, qt.IsNil) c.Assert(dst.Tags, qt.DeepEquals, openapi3.Tags{{ - Extensions: map[string]interface{}{}, Name: "bar", Description: "bar resource (src)", }, { - Extensions: map[string]interface{}{}, Name: "baz", Description: "baz resource (dst)", }, { - Extensions: map[string]interface{}{}, Name: "foo", Description: "foo resource (dst)", }}) @@ -178,15 +175,12 @@ tags: err := vervet.Merge(dst, src, true) c.Assert(err, qt.IsNil) c.Assert(dst.Tags, qt.DeepEquals, openapi3.Tags{{ - Extensions: map[string]interface{}{}, Name: "bar", Description: "bar resource (src)", }, { - Extensions: map[string]interface{}{}, Name: "baz", Description: "baz resource (dst)", }, { - Extensions: map[string]interface{}{}, Name: "foo", Description: "foo resource (src)", }}) @@ -239,9 +233,8 @@ x-extension: err := vervet.Merge(dst, src, false) c.Assert(err, qt.IsNil) c.Assert(dst.Info, qt.DeepEquals, &openapi3.Info{ - Extensions: map[string]interface{}{}, - Title: "Dst", - Version: "dst", + Title: "Dst", + Version: "dst", }) c.Assert(dst.Security, qt.DeepEquals, openapi3.SecurityRequirements{{ "Foo": []string{"up", "down"}, @@ -249,11 +242,9 @@ x-extension: "Baz": []string{"strange", "crunchy"}, }}) c.Assert(dst.Servers, qt.DeepEquals, openapi3.Servers{{ - Extensions: map[string]interface{}{}, URL: "https://example.com/foo", Description: "Foo (dst)", }, { - Extensions: map[string]interface{}{}, URL: "https://example.com/baz", Description: "Baz (dst)", }}) @@ -270,9 +261,8 @@ x-extension: err := vervet.Merge(dst, src, true) c.Assert(err, qt.IsNil) c.Assert(dst.Info, qt.DeepEquals, &openapi3.Info{ - Extensions: map[string]interface{}{}, - Title: "Src", - Version: "src", + Title: "Src", + Version: "src", }) c.Assert(dst.Security, qt.DeepEquals, openapi3.SecurityRequirements{{ "Foo": []string{}, @@ -280,11 +270,9 @@ x-extension: "Bar": []string{"read", "write"}, }}) c.Assert(dst.Servers, qt.DeepEquals, openapi3.Servers{{ - Extensions: map[string]interface{}{}, URL: "https://example.com/foo", Description: "Foo (src)", }, { - Extensions: map[string]interface{}{}, URL: "https://example.com/bar", Description: "Bar (src)", }}) @@ -318,7 +306,7 @@ paths: dst := &openapi3.T{} err := vervet.Merge(dst, src, false) c.Assert(err, qt.IsNil) - c.Assert(dst.Paths, qt.HasLen, 1) + c.Assert(dst.Paths.Len(), qt.Equals, 1) } func mustLoadFile(c *qt.C, path string) *openapi3.T { diff --git a/ref_alias_resolver.go b/ref_alias_resolver.go index ef9b8885..656e5cbe 100644 --- a/ref_alias_resolver.go +++ b/ref_alias_resolver.go @@ -1,20 +1,16 @@ package vervet import ( - "reflect" "strings" "github.com/getkin/kin-openapi/openapi3" - "github.com/mitchellh/reflectwalk" ) // refAliasResolver rewrites references in an OpenAPI document object to local // references, so that the spec is self-contained. type refAliasResolver struct { - doc *openapi3.T - refAliases map[string]string - curRefType reflect.Value - curRefField reflect.Value + doc *openapi3.T + refAliases map[string]string } // newRefAliasResolver returns a new refAliasResolver. @@ -52,26 +48,26 @@ func (l *refAliasResolver) resolveRefAlias(ref string) string { } // resolve rewrites all references in the OpenAPI document to local references. -func (l *refAliasResolver) resolve() error { - return reflectwalk.Walk(l.doc, l) -} - -// Struct implements reflectwalk.StructWalker. -func (l *refAliasResolver) Struct(v reflect.Value) error { - l.curRefType, l.curRefField = v, v.FieldByName("Ref") - return nil -} - -// StructField implements reflectwalk.StructWalker. -func (l *refAliasResolver) StructField(sf reflect.StructField, v reflect.Value) error { - if !l.curRefField.IsValid() { - return nil - } - ref := l.curRefField.String() - if ref == "" { - return nil +func (l *refAliasResolver) resolve() { + for _, path := range l.doc.Paths.InMatchingOrder() { + for _, operation := range l.doc.Paths.Value(path).Operations() { + for _, parameter := range operation.Parameters { + parameter.Ref = l.resolveRefAlias(parameter.Ref) + } + if operation.RequestBody != nil { + operation.RequestBody.Ref = l.resolveRefAlias(operation.RequestBody.Ref) + } + for _, response := range operation.Responses.Map() { + response.Ref = l.resolveRefAlias(response.Ref) + if response.Value != nil { + for _, mediaType := range response.Value.Content { + mediaType.Schema.Ref = l.resolveRefAlias(mediaType.Schema.Ref) + for _, properties := range mediaType.Schema.Value.Properties { + properties.Ref = l.resolveRefAlias(properties.Ref) + } + } + } + } + } } - ref = l.resolveRefAlias(ref) - l.curRefField.Set(reflect.ValueOf(ref)) - return nil } diff --git a/ref_index.go b/ref_index.go index c66e8d13..67c12075 100644 --- a/ref_index.go +++ b/ref_index.go @@ -1,10 +1,7 @@ package vervet import ( - "reflect" - "github.com/getkin/kin-openapi/openapi3" - "github.com/mitchellh/reflectwalk" ) // RefIndex indexes the distinct references used in an OpenAPI document. @@ -15,14 +12,51 @@ type RefIndex struct { // NewRefIndex returns a new reference index on an OpenAPI document. func NewRefIndex(doc *openapi3.T) (*RefIndex, error) { ix := &RefIndex{refs: map[string]struct{}{}} - if err := ix.index(doc); err != nil { - return nil, err - } + ix.index(doc) return ix, nil } -func (ix *RefIndex) index(doc *openapi3.T) error { - return reflectwalk.Walk(doc, ix) +func (ix *RefIndex) index(doc *openapi3.T) { + for _, schemaRef := range doc.Components.Schemas { + ix.refs[extractRef(schemaRef)] = struct{}{} + } + for _, parameterRef := range doc.Components.Parameters { + ix.refs[extractRef(parameterRef)] = struct{}{} + } + for _, headerRef := range doc.Components.Headers { + ix.refs[extractRef(headerRef)] = struct{}{} + } + for _, requestBodyRef := range doc.Components.RequestBodies { + ix.refs[extractRef(requestBodyRef)] = struct{}{} + } + for _, responseRef := range doc.Components.Responses { + ix.refs[extractRef(responseRef)] = struct{}{} + for _, content := range responseRef.Value.Content { + ix.refs[extractRef(content.Schema)] = struct{}{} + for _, propertyRef := range content.Schema.Value.Properties { + ix.refs[extractRef(propertyRef)] = struct{}{} + } + } + } + for _, securitySchemesRef := range doc.Components.SecuritySchemes { + ix.refs[extractRef(securitySchemesRef)] = struct{}{} + } + for _, exampleRef := range doc.Components.Examples { + ix.refs[extractRef(exampleRef)] = struct{}{} + } + for _, linkRef := range doc.Components.Links { + ix.refs[extractRef(linkRef)] = struct{}{} + } + for _, callbackRef := range doc.Components.Callbacks { + ix.refs[extractRef(callbackRef)] = struct{}{} + } +} + +func extractRef(componentRef openapi3.ComponentRef) string { + if componentRef == nil || componentRef.RefPath() == nil { + return "" + } + return "#" + componentRef.RefPath().Fragment } // HasRef returns whether the indexed document contains the given ref. @@ -30,37 +64,3 @@ func (ix *RefIndex) HasRef(ref string) bool { _, ok := ix.refs[ref] return ok } - -// Struct implements reflectwalk.StructWalker. -func (ix *RefIndex) Struct(v reflect.Value) error { - if !v.CanInterface() { - return nil - } - - switch val := v.Addr().Interface().(type) { - case *openapi3.SchemaRef: - ix.refs[val.Ref] = struct{}{} - case *openapi3.ParameterRef: - ix.refs[val.Ref] = struct{}{} - case *openapi3.HeaderRef: - ix.refs[val.Ref] = struct{}{} - case *openapi3.RequestBodyRef: - ix.refs[val.Ref] = struct{}{} - case *openapi3.ResponseRef: - ix.refs[val.Ref] = struct{}{} - case *openapi3.SecuritySchemeRef: - ix.refs[val.Ref] = struct{}{} - case *openapi3.ExampleRef: - ix.refs[val.Ref] = struct{}{} - case *openapi3.LinkRef: - ix.refs[val.Ref] = struct{}{} - case *openapi3.CallbackRef: - ix.refs[val.Ref] = struct{}{} - } - return nil -} - -// StructField implements reflectwalk.StructWalker. -func (*RefIndex) StructField(field reflect.StructField, v reflect.Value) error { - return nil -} diff --git a/remove_elements.go b/remove_elements.go index 15f7f370..91685680 100644 --- a/remove_elements.go +++ b/remove_elements.go @@ -1,11 +1,9 @@ package vervet import ( - "reflect" "regexp" "github.com/getkin/kin-openapi/openapi3" - "github.com/mitchellh/reflectwalk" ) // ExcludePatterns defines patterns matching elements to be removed from an @@ -49,13 +47,13 @@ func RemoveElements(doc *openapi3.T, excludes ExcludePatterns) error { } // Remove excluded paths excludedPaths := map[string]struct{}{} - for path := range doc.Paths { + for _, path := range doc.Paths.InMatchingOrder() { if ex.isExcludedPath(path) { excludedPaths[path] = struct{}{} } } for path := range excludedPaths { - delete(doc.Paths, path) + doc.Paths.Delete(path) } // Remove excluded elements if err := ex.apply(); err != nil { @@ -65,45 +63,31 @@ func RemoveElements(doc *openapi3.T, excludes ExcludePatterns) error { } func (ex *excluder) apply() error { - return reflectwalk.Walk(ex.doc, ex) -} - -// Struct implements reflectwalk.StructWalker. -func (ex *excluder) Struct(v reflect.Value) error { - if !v.CanInterface() { - return nil - } - - switch v.Interface().(type) { - case openapi3.Operation: - ex.applyOperation(v.Addr().Interface().(*openapi3.Operation)) - } - - return nil -} - -// StructField implements reflectwalk.StructWalker. -func (ex *excluder) StructField(field reflect.StructField, v reflect.Value) error { - if field.Name != "Extensions" || !v.CanInterface() { - return nil - } - - switch v.Interface().(type) { - case map[string]interface{}: - ex.applyExtensions(v.Addr().Interface().(*map[string]interface{})) + for _, pathItem := range ex.doc.Paths.Map() { + ex.applyExtensions(pathItem.Extensions) + for _, operation := range pathItem.Operations() { + ex.applyOperation(operation) + ex.applyExtensions(operation.Extensions) + if operation.Responses != nil { + ex.applyExtensions(operation.Responses.Extensions) + } + for _, responseRef := range operation.Responses.Map() { + ex.applyExtensions(responseRef.Extensions) + if responseRef.Value != nil { + ex.applyExtensions(responseRef.Value.Extensions) + } + } + } } - return nil } -func (ex *excluder) applyExtensions(extensions *map[string]interface{}) { - exts := make(map[string]interface{}, len(*extensions)) - for k, v := range *extensions { - if !ex.isExcludedExtension(k) { - exts[k] = v +func (ex *excluder) applyExtensions(extensions map[string]interface{}) { + for k := range extensions { + if ex.isExcludedExtension(k) { + delete(extensions, k) } } - *extensions = exts } func (ex *excluder) applyOperation(op *openapi3.Operation) { @@ -115,7 +99,7 @@ func (ex *excluder) applyOperation(op *openapi3.Operation) { } op.Parameters = params - for _, resp := range op.Responses { + for _, resp := range op.Responses.Map() { if resp.Value == nil { continue } diff --git a/remove_elements_test.go b/remove_elements_test.go index 43dbed7d..f124440f 100644 --- a/remove_elements_test.go +++ b/remove_elements_test.go @@ -16,24 +16,24 @@ func TestRemoveElementsExact(t *testing.T) { // Establish that the OpenAPI document has these expected features - c.Assert(doc.Paths["/examples/hello-world"], qt.Not(qt.IsNil)) - c.Assert(doc.Paths["/examples/hello-world/{id}"], qt.Not(qt.IsNil)) + c.Assert(doc.Paths.Value("/examples/hello-world"), qt.Not(qt.IsNil)) + c.Assert(doc.Paths.Value("/examples/hello-world/{id}"), qt.Not(qt.IsNil)) c.Assert( - doc.Paths["/orgs/{orgId}/projects"].Get.Responses["200"].Value.Headers["snyk-request-id"], + doc.Paths.Value("/orgs/{orgId}/projects").Get.Responses.Status(200).Value.Headers["snyk-request-id"], qt.Not(qt.IsNil), ) c.Assert( - doc.Paths["/orgs/{orgId}/projects"].Get.Responses["200"].Value.Headers["snyk-version-served"], + doc.Paths.Value("/orgs/{orgId}/projects").Get.Responses.Status(200).Value.Headers["snyk-version-served"], qt.Not(qt.IsNil), ) - c.Assert(doc.Paths["/orgs/{org_id}/projects/{project_id}"].Delete.Parameters, qt.HasLen, 4) + c.Assert(doc.Paths.Value("/orgs/{org_id}/projects/{project_id}").Delete.Parameters, qt.HasLen, 4) c.Assert( - doc.Paths["/orgs/{org_id}/projects/{project_id}"].Delete.Parameters[3].Value.Name, + doc.Paths.Value("/orgs/{org_id}/projects/{project_id}").Delete.Parameters[3].Value.Name, qt.Equals, "x-private-matter", ) - c.Assert(doc.Paths["/orgs/{orgId}/projects"].Extensions["x-snyk-api-resource"], qt.Not(qt.IsNil)) + c.Assert(doc.Paths.Value("/orgs/{orgId}/projects").Extensions["x-snyk-api-resource"], qt.Not(qt.IsNil)) c.Assert(doc.Extensions["x-snyk-api-lifecycle"], qt.Not(qt.IsNil)) // Remove some of them @@ -47,20 +47,21 @@ func TestRemoveElementsExact(t *testing.T) { // Assert their removal - c.Assert(doc.Paths["/examples/hello-world"], qt.IsNil) - c.Assert(doc.Paths["/examples/hello-world/{id}"], qt.IsNil) + c.Assert(doc.Paths.Value("/examples/hello-world"), qt.IsNil) + c.Assert(doc.Paths.Value("/examples/hello-world/{id}"), qt.IsNil) c.Assert( - doc.Paths["/orgs/{orgId}/projects"].Get.Responses["200"].Value.Headers["snyk-request-id"], + doc.Paths.Value("/orgs/{orgId}/projects").Get.Responses.Status(200).Value.Headers["snyk-request-id"], qt.IsNil, ) // now removed c.Assert( - doc.Paths["/orgs/{orgId}/projects"].Get.Responses["200"].Value.Headers["snyk-version-served"], + doc.Paths.Value("/orgs/{orgId}/projects").Get.Responses.Status(200).Value.Headers["snyk-version-served"], qt.Not(qt.IsNil), ) // still there - c.Assert(doc.Paths["/orgs/{org_id}/projects/{project_id}"].Delete.Parameters, qt.HasLen, 3) // x-private-matter removed + c.Assert(doc.Paths.Value("/orgs/{org_id}/projects/{project_id}"). + Delete.Parameters, qt.HasLen, 3) // x-private-matter removed - c.Assert(doc.Paths["/orgs/{orgId}/projects"].Extensions["x-snyk-api-resource"], qt.IsNil) // now removed - c.Assert(doc.Extensions["x-snyk-api-lifecycle"], qt.Not(qt.IsNil)) // still there + c.Assert(doc.Paths.Value("/orgs/{orgId}/projects").Extensions["x-snyk-api-resource"], qt.IsNil) // now removed + c.Assert(doc.Extensions["x-snyk-api-lifecycle"], qt.Not(qt.IsNil)) // still there } func TestRemoveElementsRegex(t *testing.T) { @@ -71,25 +72,25 @@ func TestRemoveElementsRegex(t *testing.T) { // Establish that the OpenAPI document has these expected features c.Assert( - doc.Paths["/orgs/{orgId}/projects"].Get.Responses["200"].Value.Headers["snyk-request-id"], + doc.Paths.Value("/orgs/{orgId}/projects").Get.Responses.Status(200).Value.Headers["snyk-request-id"], qt.Not(qt.IsNil), ) c.Assert( - doc.Paths["/orgs/{orgId}/projects"].Get.Responses["200"].Value.Headers["snyk-version-served"], + doc.Paths.Value("/orgs/{orgId}/projects").Get.Responses.Status(200).Value.Headers["snyk-version-served"], qt.Not(qt.IsNil), ) c.Assert( - doc.Paths["/orgs/{org_id}/projects/{project_id}"].Delete.Parameters, + doc.Paths.Value("/orgs/{org_id}/projects/{project_id}").Delete.Parameters, qt.HasLen, 4, ) c.Assert( - doc.Paths["/orgs/{org_id}/projects/{project_id}"].Delete.Parameters[3].Value.Name, + doc.Paths.Value("/orgs/{org_id}/projects/{project_id}").Delete.Parameters[3].Value.Name, qt.Equals, "x-private-matter", ) - c.Assert(doc.Paths["/orgs/{orgId}/projects"].Extensions["x-snyk-api-resource"], qt.Not(qt.IsNil)) + c.Assert(doc.Paths.Value("/orgs/{orgId}/projects").Extensions["x-snyk-api-resource"], qt.Not(qt.IsNil)) c.Assert(doc.Extensions["x-snyk-api-lifecycle"], qt.Not(qt.IsNil)) // Remove some of them @@ -103,19 +104,19 @@ func TestRemoveElementsRegex(t *testing.T) { // Assert their removal c.Assert( - doc.Paths["/orgs/{orgId}/projects"].Get.Responses["200"].Value.Headers["snyk-request-id"], + doc.Paths.Value("/orgs/{orgId}/projects").Get.Responses.Status(200).Value.Headers["snyk-request-id"], qt.Not(qt.IsNil), ) // still there c.Assert( - doc.Paths["/orgs/{orgId}/projects"].Get.Responses["200"].Value.Headers["snyk-version-served"], + doc.Paths.Value("/orgs/{orgId}/projects").Get.Responses.Status(200).Value.Headers["snyk-version-served"], qt.IsNil, ) // now removed c.Assert( - doc.Paths["/orgs/{org_id}/projects/{project_id}"].Delete.Parameters, + doc.Paths.Value("/orgs/{org_id}/projects/{project_id}").Delete.Parameters, qt.HasLen, 3, ) // x-private-matter removed - c.Assert(doc.Paths["/orgs/{orgId}/projects"].Extensions["x-snyk-api-resource"], qt.IsNil) // now removed - c.Assert(doc.Extensions["x-snyk-api-lifecycle"], qt.Not(qt.IsNil)) // still there + c.Assert(doc.Paths.Value("/orgs/{orgId}/projects").Extensions["x-snyk-api-resource"], qt.IsNil) // now removed + c.Assert(doc.Extensions["x-snyk-api-lifecycle"], qt.Not(qt.IsNil)) // still there } diff --git a/resource.go b/resource.go index 25bf5ac2..bf42b70c 100644 --- a/resource.go +++ b/resource.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "path/filepath" + "strings" "time" "github.com/bmatcuk/doublestar/v4" @@ -84,7 +85,7 @@ func (rv *ResourceVersion) Validate(ctx context.Context) error { return err } // Resource path checks. There should be at least one path per resource. - if len(rv.Paths) < 1 { + if rv.Paths.Len() < 1 { return fmt.Errorf("spec contains no paths") } return nil @@ -228,10 +229,14 @@ func LoadResourceVersionsFileset(specYamls []string) (*ResourceVersions, error) return nil, err } // Map release versions per operation - for path, pathItem := range rc.Paths { + for _, path := range rc.Paths.InMatchingOrder() { + pathItem := rc.Paths.Value(path) for _, opName := range operationNames { op := getOperationByName(pathItem, opName) if op != nil { + if op.Extensions == nil { + op.Extensions = make(map[string]any) + } op.Extensions[ExtSnykApiVersion] = rc.Version.String() opKey := operationKey{path, opName} opReleases[opKey] = append(opReleases[opKey], rc.Version) @@ -248,7 +253,8 @@ func LoadResourceVersionsFileset(specYamls []string) (*ResourceVersions, error) // Annotate each path in each resource version with the other change // versions affecting the path. This supports navigation across versions. for _, rc := range resourceVersions.versions { - for path, pathItem := range rc.Paths { + for _, path := range rc.Paths.InMatchingOrder() { + pathItem := rc.Paths.Value(path) for _, opName := range operationNames { op := getOperationByName(pathItem, opName) if op == nil { @@ -313,7 +319,7 @@ func loadResource(specPath string, versionStr string) (*ResourceVersion, error) return nil, fmt.Errorf("invalid version %q", versionStr) } - if len(doc.Paths) == 0 { + if doc.Paths.Len() == 0 { return nil, nil //nolint:nilnil //acked } @@ -331,14 +337,31 @@ func loadResource(specPath string, versionStr string) (*ResourceVersion, error) } ep := &ResourceVersion{Name: name, Document: doc, Version: version} - for path := range doc.T.Paths { - doc.T.Paths[path].Extensions[ExtSnykApiResource] = name + for _, path := range doc.T.Paths.InMatchingOrder() { + if doc.T.Paths.Value(path).Extensions == nil { + doc.T.Paths.Value(path).Extensions = make(map[string]any) + } + doc.T.Paths.Value(path).Extensions[ExtSnykApiResource] = name } return ep, nil } // Localize rewrites all references in an OpenAPI document to local references. func Localize(ctx context.Context, doc *Document) error { - doc.InternalizeRefs(ctx, nil) + doc.InternalizeRefs(ctx, func(t *openapi3.T, componentRef openapi3.ComponentRef) string { + ref := componentRef.RefString() + if ref == "" { + return "" + } + split := strings.SplitN(ref, "#", 2) + if len(split) == 2 { + return filepath.Base(split[1]) + } + ref = split[0] + for ext := filepath.Ext(ref); len(ext) > 0; ext = filepath.Ext(ref) { + ref = strings.TrimSuffix(ref, ext) + } + return filepath.Base(ref) + }) return doc.ResolveRefs() } diff --git a/resource_versions.go b/resource_versions.go index ac17d898..3712ea44 100644 --- a/resource_versions.go +++ b/resource_versions.go @@ -20,7 +20,7 @@ func (s resourceVersionsSlice) validate() error { } else if err != nil { return fmt.Errorf("validation failed: %w", err) } - for path := range ep.Paths { + for _, path := range ep.Paths.InMatchingOrder() { if conflict, ok := resourcePaths[path]; ok { return fmt.Errorf("conflict: %q %q", conflict, ep.sourcePrefix) } @@ -65,7 +65,7 @@ func (s resourceVersionsSlice) at(v Version) (*openapi3.T, error) { return nil, ErrNoMatchingVersion } if result.Extensions == nil { - result.Extensions = map[string]interface{}{} + result.Extensions = map[string]any{} } result.Extensions[ExtSnykApiLifecycle] = v.LifecycleAt(time.Time{}).String() return result, nil diff --git a/spec.go b/spec.go index e118de26..7240fbb3 100644 --- a/spec.go +++ b/spec.go @@ -115,7 +115,8 @@ func (sv *SpecVersions) resolveOperations() error { // Operations declared in this spec become active for the next version // at this stability. nextActiveOps := operationVersionMap{} - for path, pathItem := range doc.Paths { + for _, path := range doc.Paths.InMatchingOrder() { + pathItem := doc.Paths.Value(path) for _, opName := range operationNames { op := getOperationByName(pathItem, opName) if op != nil { @@ -129,7 +130,7 @@ func (sv *SpecVersions) resolveOperations() error { // Operations currently active for this versions's stability get // carried forward and remain active. for opKey, opValue := range currentActiveOps { - currentPathItem := doc.Paths[opKey.path] + currentPathItem := doc.Paths.Value(opKey.path) // skip promoting sunset operations into current document lc, ok := opValue.operation.Extensions[ExtSnykApiLifecycle].(string) @@ -145,7 +146,7 @@ func (sv *SpecVersions) resolveOperations() error { Servers: opValue.pathItem.Servers, Parameters: opValue.pathItem.Parameters, } - doc.Paths[opKey.path] = currentPathItem + doc.Paths.Set(opKey.path, currentPathItem) } currentOp := getOperationByName(currentPathItem, opKey.operation) if currentOp == nil { diff --git a/spec_test.go b/spec_test.go index ce0c3844..4023d13e 100644 --- a/spec_test.go +++ b/spec_test.go @@ -135,7 +135,7 @@ func TestSpecs(t *testing.T) { c.Assert(err, qt.IsNil) c.Assert(version, qt.Equals, t.match) for _, expected := range t.hasVersions { - pathItem := spec.Paths[expected.path] + pathItem := spec.Paths.Value(expected.path) if !expected.shouldExist { c.Assert(pathItem, qt.IsNil) diff --git a/testdata/.vervet/resource/version/index.ts.tmpl b/testdata/.vervet/resource/version/index.ts.tmpl index 78ed4977..01063cf4 100644 --- a/testdata/.vervet/resource/version/index.ts.tmpl +++ b/testdata/.vervet/resource/version/index.ts.tmpl @@ -1,4 +1,4 @@ -{{ range $path, $pathItem := .ResourceVersion.Document.Paths -}} +{{ range $path, $pathItem := .ResourceVersion.Document.Paths.Map -}} {{ range $method, $operation := $pathItem|pathOperations -}} export {{ "{" }} {{ $operation.OperationID }} {{ "}" }} from './{{ $operation.OperationID }}'; {{ end }} diff --git a/testdata/generators.yaml b/testdata/generators.yaml index 105385f6..4a66281a 100644 --- a/testdata/generators.yaml +++ b/testdata/generators.yaml @@ -6,7 +6,7 @@ version-controller: scope: version files: |- {{- $path := .Path -}} - {{- range $_, $pathItem := .ResourceVersion.Document.Paths -}} + {{- range $_, $pathItem := .ResourceVersion.Document.Paths.Map -}} {{- range $method, $operation := $pathItem|pathOperations -}} {{- $operationId := $operation.OperationID -}} {{- $ctx := map "Context" . "OperationId" $operationId }} diff --git a/versionware/validator.go b/versionware/validator.go index fb4f6b6d..a65f75ae 100644 --- a/versionware/validator.go +++ b/versionware/validator.go @@ -1,6 +1,7 @@ package versionware import ( + "context" "errors" "fmt" "net/http" @@ -43,16 +44,17 @@ type ValidatorConfig struct { var defaultValidatorConfig = ValidatorConfig{ VersionError: DefaultVersionError, Options: []openapi3filter.ValidatorOption{ - openapi3filter.OnErr(func(w http.ResponseWriter, status int, code openapi3filter.ErrCode, _ error) { - statusText := http.StatusText(http.StatusInternalServerError) - switch code { - case openapi3filter.ErrCodeCannotFindRoute: - statusText = "Not Found" - case openapi3filter.ErrCodeRequestInvalid: - statusText = "Bad Request" - } - http.Error(w, statusText, status) - }), + openapi3filter.OnErr( + func(ctx context.Context, w http.ResponseWriter, status int, code openapi3filter.ErrCode, _ error) { + statusText := http.StatusText(http.StatusInternalServerError) + switch code { + case openapi3filter.ErrCodeCannotFindRoute: + statusText = "Not Found" + case openapi3filter.ErrCodeRequestInvalid: + statusText = "Bad Request" + } + http.Error(w, statusText, status) + }), }, } From 040402d65820d12e9d8a2c945bca11dae2622110 Mon Sep 17 00:00:00 2001 From: Jatin Naik Date: Wed, 14 Aug 2024 07:22:29 +0100 Subject: [PATCH 2/6] fix: non-relective walk for inlining --- collator.go | 2 +- inliner.go | 245 +++++++++++++++++++++++++++++----------------------- 2 files changed, 136 insertions(+), 111 deletions(-) diff --git a/collator.go b/collator.go index 60c28128..300bf49e 100644 --- a/collator.go +++ b/collator.go @@ -272,7 +272,7 @@ func (c *Collator) mergePaths(rv *ResourceVersion) error { } var errs error for k, v := range rv.T.Paths.Map() { - for opName, opValue := range rv.T.Paths.Value(k).Operations() { + for opName, opValue := range v.Operations() { route := routeForPath(k, opName) if _, ok := c.seenRoutes[route]; ok { if c.useFirstRoute { diff --git a/inliner.go b/inliner.go index 37ae9a91..74813da9 100644 --- a/inliner.go +++ b/inliner.go @@ -25,142 +25,168 @@ func (in *Inliner) AddRef(ref string) { // Inline inlines all the JSON References previously indicated with AddRef in // the given OpenAPI document. func (in *Inliner) Inline(doc *openapi3.T) error { - for _, path := range doc.Paths.InMatchingOrder() { - for _, operation := range doc.Paths.Value(path).Operations() { - for _, parameter := range operation.Parameters { - parameter.Ref = in.removeIfMatched(parameter.Ref) - in.checkSchemaRef(parameter.Value.Schema) - for _, exampleRef := range parameter.Value.Examples { - exampleRef.Ref = in.removeIfMatched(exampleRef.Ref) - } - } - if operation.RequestBody != nil { - operation.RequestBody.Ref = in.removeIfMatched(operation.RequestBody.Ref) - } + if len(in.refs) == 0 { + return nil + } + + for _, pathItem := range doc.Paths.Map() { + in.checkParameters(pathItem.Parameters) + + for _, operation := range pathItem.Operations() { + in.checkParameters(operation.Parameters) + in.checkResponseBody(operation.RequestBody) for _, response := range operation.Responses.Map() { - response.Ref = in.removeIfMatched(response.Ref) + if in.matched(response.Ref) { + removeRefsResponseAndChildren(response) + } if response.Value != nil { - for _, mediaType := range response.Value.Content { - in.checkSchemaRef(mediaType.Schema) - for _, example := range mediaType.Examples { - example.Ref = in.removeIfMatched(example.Ref) - } + for _, headerRef := range response.Value.Headers { + in.checkHeaderRefMatch(headerRef) } + in.checkContent(response.Value.Content) } } } - } return nil } -func (in *Inliner) checkSchemaRef(schema *openapi3.SchemaRef) { - schema.Ref = in.removeIfMatched(schema.Ref) - for _, properties := range schema.Value.Properties { - properties.Ref = in.removeIfMatched(properties.Ref) - } +func (in *Inliner) matched(ref string) bool { + _, match := in.refs[ref] + return match } + func (in *Inliner) removeIfMatched(ref string) string { - if _, match := in.refs[ref]; match { + if in.matched(ref) { return "" } return ref } -// Struct implements reflectwalk.StructWalker. -func (in *Inliner) Struct(v reflect.Value) error { - if !v.CanInterface() { - return nil - } - switch val := v.Interface().(type) { - case openapi3.SchemaRef: - if _, ok := in.refs[val.Ref]; ok { - valPointer := v.Addr().Interface().(*openapi3.SchemaRef) - refRemover := NewRefRemover(valPointer) - err := refRemover.RemoveRef() - if err != nil { - return err - } +func (in *Inliner) checkContent(content openapi3.Content) { + for _, mediaType := range content { + in.checkSchemaRef(mediaType.Schema) + for _, example := range mediaType.Examples { + example.Ref = in.removeIfMatched(example.Ref) } - case openapi3.ParameterRef: - if _, ok := in.refs[val.Ref]; ok { - valPointer := v.Addr().Interface().(*openapi3.ParameterRef) - refRemover := NewRefRemover(valPointer) - err := refRemover.RemoveRef() - if err != nil { - return err - } - } - case openapi3.HeaderRef: - if _, ok := in.refs[val.Ref]; ok { - valPointer := v.Addr().Interface().(*openapi3.HeaderRef) - refRemover := NewRefRemover(valPointer) - err := refRemover.RemoveRef() - if err != nil { - return err - } - } - case openapi3.RequestBodyRef: - if _, ok := in.refs[val.Ref]; ok { - valPointer := v.Addr().Interface().(*openapi3.RequestBodyRef) - refRemover := NewRefRemover(valPointer) - err := refRemover.RemoveRef() - if err != nil { - return err - } + } +} + +func (in *Inliner) checkHeaderRefMatch(headerRef *openapi3.HeaderRef) { + if in.matched(headerRef.Ref) { + removeHeaderRefsAndChildren(headerRef) + } + if headerRef.Value != nil { + in.checkSchemaRef(headerRef.Value.Schema) + } +} + +func removeHeaderRefsAndChildren(headerRef *openapi3.HeaderRef) { + headerRef.Ref = "" + if headerRef.Value != nil { + removeRefsForSchemaAndChildren(headerRef.Value.Schema) + removeRefsForExamples(headerRef.Value.Examples) + } +} + +func (in *Inliner) checkParameters(parameters openapi3.Parameters) { + for _, parameterRef := range parameters { + in.checkParameterRef(parameterRef) + } +} + +func (in *Inliner) checkParameterRef(parameterRef *openapi3.ParameterRef) { + if in.matched(parameterRef.Ref) { + removeParameterRefsAndChildren(parameterRef) + } + in.checkSchemaRef(parameterRef.Value.Schema) +} + +func (in *Inliner) checkSchemaRef(schemas ...*openapi3.SchemaRef) { + if schemas == nil { + return + } + for _, schema := range schemas { + if schema == nil { + return } - case openapi3.ResponseRef: - if _, ok := in.refs[val.Ref]; ok { - valPointer := v.Addr().Interface().(*openapi3.ResponseRef) - refRemover := NewRefRemover(valPointer) - err := refRemover.RemoveRef() - if err != nil { - return err - } + if in.matched(schema.Ref) { + removeRefsForSchemaAndChildren(schema) } - case openapi3.SecuritySchemeRef: - if _, ok := in.refs[val.Ref]; ok { - valPointer := v.Addr().Interface().(*openapi3.SecuritySchemeRef) - refRemover := NewRefRemover(valPointer) - err := refRemover.RemoveRef() - if err != nil { - return err - } + if schema.Value != nil { + in.checkSchemaRef(schemaRefsFromSchemas(schema.Value.Properties)...) + in.checkSchemaRef(schema.Value.Items) + in.checkSchemaRef(schema.Value.AllOf...) + in.checkSchemaRef(schema.Value.AnyOf...) + in.checkSchemaRef(schema.Value.OneOf...) + in.checkSchemaRef(schema.Value.Not) } - case openapi3.ExampleRef: - if _, ok := in.refs[val.Ref]; ok { - valPointer := v.Addr().Interface().(*openapi3.ExampleRef) - refRemover := NewRefRemover(valPointer) - err := refRemover.RemoveRef() - if err != nil { - return err - } + } +} + +func (in *Inliner) checkResponseBody(body *openapi3.RequestBodyRef) { + if body != nil { + if in.matched(body.Ref) { + body.Ref = "" + removeRefsContentAndChildren(body.Value.Content) } - case openapi3.LinkRef: - if _, ok := in.refs[val.Ref]; ok { - valPointer := v.Addr().Interface().(*openapi3.LinkRef) - refRemover := NewRefRemover(valPointer) - err := refRemover.RemoveRef() - if err != nil { - return err - } + in.checkContent(body.Value.Content) + } +} + +func removeRefsForSchemaAndChildren(schemas ...*openapi3.SchemaRef) { + if schemas == nil { + return + } + for _, schema := range schemas { + if schema == nil { + return } - case openapi3.CallbackRef: - if _, ok := in.refs[val.Ref]; ok { - valPointer := v.Addr().Interface().(*openapi3.CallbackRef) - refRemover := NewRefRemover(valPointer) - err := refRemover.RemoveRef() - if err != nil { - return err - } + schema.Ref = "" + if schema.Value != nil { + removeRefsForSchemaAndChildren(schemaRefsFromSchemas(schema.Value.Properties)...) + removeRefsForSchemaAndChildren(schema.Value.Items) + removeRefsForSchemaAndChildren(schema.Value.AllOf...) + removeRefsForSchemaAndChildren(schema.Value.AnyOf...) + removeRefsForSchemaAndChildren(schema.Value.OneOf...) + removeRefsForSchemaAndChildren(schema.Value.Not) } } - return nil } -// StructField implements reflectwalk.StructWalker. -func (in *Inliner) StructField(field reflect.StructField, v reflect.Value) error { - return nil +func schemaRefsFromSchemas(properties openapi3.Schemas) []*openapi3.SchemaRef { + refs := make([]*openapi3.SchemaRef, 0, len(properties)) + for _, ref := range properties { + refs = append(refs, ref) + } + return refs +} + +func removeParameterRefsAndChildren(parameter *openapi3.ParameterRef) { + parameter.Ref = "" + removeRefsForSchemaAndChildren(parameter.Value.Schema) + removeRefsForExamples(parameter.Value.Examples) +} + +func removeRefsForExamples(examples openapi3.Examples) { + for _, example := range examples { + example.Ref = "" + } +} + +func removeRefsResponseAndChildren(response *openapi3.ResponseRef) { + response.Ref = "" + removeRefsContentAndChildren(response.Value.Content) + for _, ref := range response.Value.Headers { + removeHeaderRefsAndChildren(ref) + } +} + +func removeRefsContentAndChildren(content openapi3.Content) { + for _, mediaType := range content { + removeRefsForSchemaAndChildren(mediaType.Schema) + removeRefsForExamples(mediaType.Examples) + } } // RefRemover removes the ref from the component. @@ -168,7 +194,6 @@ type RefRemover struct { target interface{} } -// NewRefRemover returns a new RefRemover instance. func NewRefRemover(target interface{}) *RefRemover { return &RefRemover{target: target} } From ef0c1d3b8ef56f51433c95536a853f263818c402 Mon Sep 17 00:00:00 2001 From: Jatin Naik Date: Wed, 14 Aug 2024 10:24:59 +0100 Subject: [PATCH 3/6] fix: refactor inliner to make remove refs generic - also factored out the resolve refs function --- collator_test.go | 5 +- inliner.go | 211 ++++++++++++++-------------------- internal/simplebuild/build.go | 2 +- resource.go | 36 +++--- 4 files changed, 112 insertions(+), 142 deletions(-) diff --git a/collator_test.go b/collator_test.go index d26fd257..52ed2886 100644 --- a/collator_test.go +++ b/collator_test.go @@ -17,10 +17,7 @@ func TestRefRemover(t *testing.T) { errDoc := resp400.Value.Content["application/vnd.api+json"].Schema c.Assert(err, qt.IsNil) c.Assert("{\"$ref\":\"../errors.yaml#/ErrorDocument\"}", qt.JSONEquals, errDoc) - in := vervet.NewRefRemover(errDoc) - err = in.RemoveRef() - c.Assert(err, qt.IsNil) - c.Assert(err, qt.IsNil) + vervet.RemoveRefs(errDoc) //nolint:lll // acked c.Assert("{\"additionalProperties\":false,\"example\":{\"errors\":[{\"detail\":\"Permission denied for this "+ "resource\",\"status\":\"403\"}],\"jsonapi\":{\"version\":\"1.0\"}},\"properties\":{\"errors\":{\"example\":"+ diff --git a/inliner.go b/inliner.go index 74813da9..a984f0b0 100644 --- a/inliner.go +++ b/inliner.go @@ -1,10 +1,8 @@ package vervet import ( - "reflect" - + "fmt" "github.com/getkin/kin-openapi/openapi3" - "github.com/mitchellh/reflectwalk" ) // Inliner inlines the component. @@ -37,7 +35,7 @@ func (in *Inliner) Inline(doc *openapi3.T) error { in.checkResponseBody(operation.RequestBody) for _, response := range operation.Responses.Map() { if in.matched(response.Ref) { - removeRefsResponseAndChildren(response) + RemoveRefs(response) } if response.Value != nil { for _, headerRef := range response.Value.Headers { @@ -74,21 +72,13 @@ func (in *Inliner) checkContent(content openapi3.Content) { func (in *Inliner) checkHeaderRefMatch(headerRef *openapi3.HeaderRef) { if in.matched(headerRef.Ref) { - removeHeaderRefsAndChildren(headerRef) + RemoveRefs(headerRef) } if headerRef.Value != nil { in.checkSchemaRef(headerRef.Value.Schema) } } -func removeHeaderRefsAndChildren(headerRef *openapi3.HeaderRef) { - headerRef.Ref = "" - if headerRef.Value != nil { - removeRefsForSchemaAndChildren(headerRef.Value.Schema) - removeRefsForExamples(headerRef.Value.Examples) - } -} - func (in *Inliner) checkParameters(parameters openapi3.Parameters) { for _, parameterRef := range parameters { in.checkParameterRef(parameterRef) @@ -97,7 +87,7 @@ func (in *Inliner) checkParameters(parameters openapi3.Parameters) { func (in *Inliner) checkParameterRef(parameterRef *openapi3.ParameterRef) { if in.matched(parameterRef.Ref) { - removeParameterRefsAndChildren(parameterRef) + RemoveRefs(parameterRef) } in.checkSchemaRef(parameterRef.Value.Schema) } @@ -111,7 +101,7 @@ func (in *Inliner) checkSchemaRef(schemas ...*openapi3.SchemaRef) { return } if in.matched(schema.Ref) { - removeRefsForSchemaAndChildren(schema) + RemoveRefs(schema) } if schema.Value != nil { in.checkSchemaRef(schemaRefsFromSchemas(schema.Value.Properties)...) @@ -124,127 +114,104 @@ func (in *Inliner) checkSchemaRef(schemas ...*openapi3.SchemaRef) { } } -func (in *Inliner) checkResponseBody(body *openapi3.RequestBodyRef) { - if body != nil { - if in.matched(body.Ref) { - body.Ref = "" - removeRefsContentAndChildren(body.Value.Content) - } - in.checkContent(body.Value.Content) - } -} - -func removeRefsForSchemaAndChildren(schemas ...*openapi3.SchemaRef) { - if schemas == nil { - return - } - for _, schema := range schemas { - if schema == nil { - return - } - schema.Ref = "" - if schema.Value != nil { - removeRefsForSchemaAndChildren(schemaRefsFromSchemas(schema.Value.Properties)...) - removeRefsForSchemaAndChildren(schema.Value.Items) - removeRefsForSchemaAndChildren(schema.Value.AllOf...) - removeRefsForSchemaAndChildren(schema.Value.AnyOf...) - removeRefsForSchemaAndChildren(schema.Value.OneOf...) - removeRefsForSchemaAndChildren(schema.Value.Not) - } - } -} - func schemaRefsFromSchemas(properties openapi3.Schemas) []*openapi3.SchemaRef { - refs := make([]*openapi3.SchemaRef, 0, len(properties)) + refs := []*openapi3.SchemaRef{} for _, ref := range properties { refs = append(refs, ref) } return refs } -func removeParameterRefsAndChildren(parameter *openapi3.ParameterRef) { - parameter.Ref = "" - removeRefsForSchemaAndChildren(parameter.Value.Schema) - removeRefsForExamples(parameter.Value.Examples) -} - -func removeRefsForExamples(examples openapi3.Examples) { - for _, example := range examples { - example.Ref = "" - } -} - -func removeRefsResponseAndChildren(response *openapi3.ResponseRef) { - response.Ref = "" - removeRefsContentAndChildren(response.Value.Content) - for _, ref := range response.Value.Headers { - removeHeaderRefsAndChildren(ref) - } -} - -func removeRefsContentAndChildren(content openapi3.Content) { - for _, mediaType := range content { - removeRefsForSchemaAndChildren(mediaType.Schema) - removeRefsForExamples(mediaType.Examples) +func (in *Inliner) checkResponseBody(body *openapi3.RequestBodyRef) { + if body != nil { + if in.matched(body.Ref) { + body.Ref = "" + RemoveRefs(body.Value.Content) + } + in.checkContent(body.Value.Content) } } -// RefRemover removes the ref from the component. -type RefRemover struct { - target interface{} -} - -func NewRefRemover(target interface{}) *RefRemover { - return &RefRemover{target: target} -} - -// RemoveRef removes all $ref locations from an OpenAPI document object +// RemoveRefs removes all $ref locations from an OpenAPI document object // fragment. If the reference has already been resolved, this has the effect of // "inlining" the formerly referenced object when serializing the OpenAPI // document. -func (rr *RefRemover) RemoveRef() error { - return reflectwalk.Walk(rr.target, rr) -} +func RemoveRefs(target interface{}) { + switch v := target.(type) { + case nil: + return + case openapi3.Content: + for _, mediaType := range v { + RemoveRefs(mediaType.Schema) + RemoveRefs(mediaType.Examples) + } -// Struct implements reflectwalk.StructWalker. -func (rr *RefRemover) Struct(v reflect.Value) error { - if !v.CanInterface() { - return nil - } - switch v.Interface().(type) { - case openapi3.SchemaRef: - valPointer := v.Addr().Interface().(*openapi3.SchemaRef) - valPointer.Ref = "" - case openapi3.ParameterRef: - valPointer := v.Addr().Interface().(*openapi3.ParameterRef) - valPointer.Ref = "" - case openapi3.HeaderRef: - valPointer := v.Addr().Interface().(*openapi3.HeaderRef) - valPointer.Ref = "" - case openapi3.RequestBodyRef: - valPointer := v.Addr().Interface().(*openapi3.RequestBodyRef) - valPointer.Ref = "" - case openapi3.ResponseRef: - valPointer := v.Addr().Interface().(*openapi3.ResponseRef) - valPointer.Ref = "" - case openapi3.SecuritySchemeRef: - valPointer := v.Addr().Interface().(*openapi3.SecuritySchemeRef) - valPointer.Ref = "" - case openapi3.ExampleRef: - valPointer := v.Addr().Interface().(*openapi3.ExampleRef) - valPointer.Ref = "" - case openapi3.LinkRef: - valPointer := v.Addr().Interface().(*openapi3.LinkRef) - valPointer.Ref = "" - case openapi3.CallbackRef: - valPointer := v.Addr().Interface().(*openapi3.CallbackRef) - valPointer.Ref = "" - } + case openapi3.Schemas: + for _, schema := range v { + RemoveRefs(schema) + } + case openapi3.SchemaRefs: + for _, schema := range v { + RemoveRefs(schema) + } + case openapi3.Headers: + for _, header := range v { + RemoveRefs(header) + } + case openapi3.Parameter: + RemoveRefs(v.Schema) - return nil -} + case openapi3.Examples: + for _, example := range v { + RemoveRefs(example) + } -// StructField implements reflectwalk.StructWalker. -func (rr *RefRemover) StructField(field reflect.StructField, v reflect.Value) error { - return nil + case *openapi3.ExampleRef: + v.Ref = "" + + case *openapi3.ParameterRef: + if v == nil { + return + } + v.Ref = "" + if v.Value != nil { + RemoveRefs(v.Value.Schema) + RemoveRefs(v.Value.Content) + RemoveRefs(v.Value.Examples) + } + case *openapi3.ResponseRef: + if v == nil { + return + } + v.Ref = "" + if v.Value != nil { + RemoveRefs(v.Value.Content) + RemoveRefs(v.Value.Headers) + } + case *openapi3.SchemaRef: + if v == nil { + return + } + v.Ref = "" + if v.Value != nil { + RemoveRefs(v.Value.Properties) + RemoveRefs(v.Value.Items) + RemoveRefs(v.Value.AllOf) + RemoveRefs(v.Value.AnyOf) + RemoveRefs(v.Value.OneOf) + RemoveRefs(v.Value.Not) + } + case *openapi3.HeaderRef: + if v == nil { + return + } + v.Ref = "" + if v.Value != nil { + RemoveRefs(v.Value.Parameter) + } + default: + //intentional panic, have covered all the types in kin-openapi v0.127.0 + //might fail in the future if new types are added, should be caught in tests + panic(fmt.Sprintf("unhandled type %v", target)) + } } diff --git a/internal/simplebuild/build.go b/internal/simplebuild/build.go index 79674f4f..688c0ea7 100644 --- a/internal/simplebuild/build.go +++ b/internal/simplebuild/build.go @@ -151,7 +151,7 @@ func LoadPaths(ctx context.Context, api *config.API) (Operations, error) { return nil, fmt.Errorf("invalid version %q", versionStr) } - doc.InternalizeRefs(ctx, nil) + doc.InternalizeRefs(ctx, vervet.ResolveRefsWithoutSourceName) err = doc.ResolveRefs() if err != nil { return nil, fmt.Errorf("failed to localize refs: %w", err) diff --git a/resource.go b/resource.go index bf42b70c..82ee7e01 100644 --- a/resource.go +++ b/resource.go @@ -348,20 +348,26 @@ func loadResource(specPath string, versionStr string) (*ResourceVersion, error) // Localize rewrites all references in an OpenAPI document to local references. func Localize(ctx context.Context, doc *Document) error { - doc.InternalizeRefs(ctx, func(t *openapi3.T, componentRef openapi3.ComponentRef) string { - ref := componentRef.RefString() - if ref == "" { - return "" - } - split := strings.SplitN(ref, "#", 2) - if len(split) == 2 { - return filepath.Base(split[1]) - } - ref = split[0] - for ext := filepath.Ext(ref); len(ext) > 0; ext = filepath.Ext(ref) { - ref = strings.TrimSuffix(ref, ext) - } - return filepath.Base(ref) - }) + doc.InternalizeRefs(ctx, ResolveRefsWithoutSourceName) return doc.ResolveRefs() } + +// ResolveRefsWithoutSourceName resolves references without the source url/file name in ref +// background: this was the way kin-openapi used to resolve references, but it was changed +// in the recent versions(v0.127.0) to include the filename in the ref name. Although this +// method prevents conflicts, it causes existing specs to break. +func ResolveRefsWithoutSourceName(t *openapi3.T, componentRef openapi3.ComponentRef) string { + ref := componentRef.RefString() + if ref == "" { + return "" + } + split := strings.SplitN(ref, "#", 2) + if len(split) == 2 { + return filepath.Base(split[1]) + } + ref = split[0] + for ext := filepath.Ext(ref); len(ext) > 0; ext = filepath.Ext(ref) { + ref = strings.TrimSuffix(ref, ext) + } + return filepath.Base(ref) +} From c4d39cea63bfd589083e79a51a4ba28ed22943f3 Mon Sep 17 00:00:00 2001 From: Jatin Naik Date: Thu, 15 Aug 2024 10:14:02 +0100 Subject: [PATCH 4/6] feat: add non-relective openapi walker, for checking refs --- document.go | 1 + inliner.go | 250 +++++++++----------------- internal/openapiwalker/walker.go | 293 +++++++++++++++++++++++++++++++ ref_alias_resolver.go | 60 ++++--- 4 files changed, 419 insertions(+), 185 deletions(-) create mode 100644 internal/openapiwalker/walker.go diff --git a/document.go b/document.go index cf4060c4..c5e0d9c8 100644 --- a/document.go +++ b/document.go @@ -84,6 +84,7 @@ func NewDocumentFile(specFile string) (_ *Document, returnErr error) { l := openapi3.NewLoader() l.IsExternalRefsAllowed = true + err = l.ResolveRefsIn(&t, specURL) if err != nil { return nil, fmt.Errorf("failed to load %q: %w", specBase, err) diff --git a/inliner.go b/inliner.go index a984f0b0..3ced6b6a 100644 --- a/inliner.go +++ b/inliner.go @@ -1,8 +1,9 @@ package vervet import ( - "fmt" "github.com/getkin/kin-openapi/openapi3" + + "github.com/snyk/vervet/v7/internal/openapiwalker" ) // Inliner inlines the component. @@ -10,6 +11,60 @@ type Inliner struct { refs map[string]struct{} } +func (in *Inliner) ProcessCallbackRef(ref *openapi3.CallbackRef) { + if in.matched(ref.Ref) { + RemoveRefs(ref) + } +} + +func (in *Inliner) ProcessExampleRef(ref *openapi3.ExampleRef) { + if in.matched(ref.Ref) { + RemoveRefs(ref) + } +} + +func (in *Inliner) ProcessHeaderRef(ref *openapi3.HeaderRef) { + if in.matched(ref.Ref) { + RemoveRefs(ref) + } +} + +func (in *Inliner) ProcessLinkRef(ref *openapi3.LinkRef) { + if in.matched(ref.Ref) { + RemoveRefs(ref) + } +} + +func (in *Inliner) ProcessParameterRef(ref *openapi3.ParameterRef) { + if in.matched(ref.Ref) { + RemoveRefs(ref) + } +} + +func (in *Inliner) ProcessRequestBodyRef(ref *openapi3.RequestBodyRef) { + if in.matched(ref.Ref) { + RemoveRefs(ref) + } +} + +func (in *Inliner) ProcessResponseRef(ref *openapi3.ResponseRef) { + if in.matched(ref.Ref) { + RemoveRefs(ref) + } +} + +func (in *Inliner) ProcessSchemaRef(ref *openapi3.SchemaRef) { + if in.matched(ref.Ref) { + RemoveRefs(ref) + } +} + +func (in *Inliner) ProcessSecuritySchemeRef(ref *openapi3.SecuritySchemeRef) { + if in.matched(ref.Ref) { + RemoveRefs(ref) + } +} + // NewInliner returns a new Inliner instance. func NewInliner() *Inliner { return &Inliner{refs: map[string]struct{}{}} @@ -26,26 +81,8 @@ func (in *Inliner) Inline(doc *openapi3.T) error { if len(in.refs) == 0 { return nil } + openapiwalker.ProcessRefs(doc, in) - for _, pathItem := range doc.Paths.Map() { - in.checkParameters(pathItem.Parameters) - - for _, operation := range pathItem.Operations() { - in.checkParameters(operation.Parameters) - in.checkResponseBody(operation.RequestBody) - for _, response := range operation.Responses.Map() { - if in.matched(response.Ref) { - RemoveRefs(response) - } - if response.Value != nil { - for _, headerRef := range response.Value.Headers { - in.checkHeaderRefMatch(headerRef) - } - in.checkContent(response.Value.Content) - } - } - } - } return nil } @@ -54,164 +91,49 @@ func (in *Inliner) matched(ref string) bool { return match } -func (in *Inliner) removeIfMatched(ref string) string { - if in.matched(ref) { - return "" - } - return ref +// RemoveRefs removes all $ref locations from an OpenAPI document object +// fragment. If the reference has already been resolved, this has the effect of +// "inlining" the formerly referenced object when serializing the OpenAPI +// document. +func RemoveRefs(target interface{}) { + openapiwalker.ProcessRefs(target, clearRefs{}) } -func (in *Inliner) checkContent(content openapi3.Content) { - for _, mediaType := range content { - in.checkSchemaRef(mediaType.Schema) - for _, example := range mediaType.Examples { - example.Ref = in.removeIfMatched(example.Ref) - } - } +type clearRefs struct { } -func (in *Inliner) checkHeaderRefMatch(headerRef *openapi3.HeaderRef) { - if in.matched(headerRef.Ref) { - RemoveRefs(headerRef) - } - if headerRef.Value != nil { - in.checkSchemaRef(headerRef.Value.Schema) - } +func (c clearRefs) ProcessCallbackRef(ref *openapi3.CallbackRef) { + ref.Ref = "" } -func (in *Inliner) checkParameters(parameters openapi3.Parameters) { - for _, parameterRef := range parameters { - in.checkParameterRef(parameterRef) - } +func (c clearRefs) ProcessExampleRef(ref *openapi3.ExampleRef) { + ref.Ref = "" } -func (in *Inliner) checkParameterRef(parameterRef *openapi3.ParameterRef) { - if in.matched(parameterRef.Ref) { - RemoveRefs(parameterRef) - } - in.checkSchemaRef(parameterRef.Value.Schema) +func (c clearRefs) ProcessHeaderRef(ref *openapi3.HeaderRef) { + ref.Ref = "" } -func (in *Inliner) checkSchemaRef(schemas ...*openapi3.SchemaRef) { - if schemas == nil { - return - } - for _, schema := range schemas { - if schema == nil { - return - } - if in.matched(schema.Ref) { - RemoveRefs(schema) - } - if schema.Value != nil { - in.checkSchemaRef(schemaRefsFromSchemas(schema.Value.Properties)...) - in.checkSchemaRef(schema.Value.Items) - in.checkSchemaRef(schema.Value.AllOf...) - in.checkSchemaRef(schema.Value.AnyOf...) - in.checkSchemaRef(schema.Value.OneOf...) - in.checkSchemaRef(schema.Value.Not) - } - } +func (c clearRefs) ProcessLinkRef(ref *openapi3.LinkRef) { + ref.Ref = "" } -func schemaRefsFromSchemas(properties openapi3.Schemas) []*openapi3.SchemaRef { - refs := []*openapi3.SchemaRef{} - for _, ref := range properties { - refs = append(refs, ref) - } - return refs +func (c clearRefs) ProcessParameterRef(ref *openapi3.ParameterRef) { + ref.Ref = "" } -func (in *Inliner) checkResponseBody(body *openapi3.RequestBodyRef) { - if body != nil { - if in.matched(body.Ref) { - body.Ref = "" - RemoveRefs(body.Value.Content) - } - in.checkContent(body.Value.Content) - } +func (c clearRefs) ProcessRequestBodyRef(ref *openapi3.RequestBodyRef) { + ref.Ref = "" } -// RemoveRefs removes all $ref locations from an OpenAPI document object -// fragment. If the reference has already been resolved, this has the effect of -// "inlining" the formerly referenced object when serializing the OpenAPI -// document. -func RemoveRefs(target interface{}) { - switch v := target.(type) { - case nil: - return - case openapi3.Content: - for _, mediaType := range v { - RemoveRefs(mediaType.Schema) - RemoveRefs(mediaType.Examples) - } - - case openapi3.Schemas: - for _, schema := range v { - RemoveRefs(schema) - } - case openapi3.SchemaRefs: - for _, schema := range v { - RemoveRefs(schema) - } - case openapi3.Headers: - for _, header := range v { - RemoveRefs(header) - } - case openapi3.Parameter: - RemoveRefs(v.Schema) - - case openapi3.Examples: - for _, example := range v { - RemoveRefs(example) - } - - case *openapi3.ExampleRef: - v.Ref = "" - - case *openapi3.ParameterRef: - if v == nil { - return - } - v.Ref = "" - if v.Value != nil { - RemoveRefs(v.Value.Schema) - RemoveRefs(v.Value.Content) - RemoveRefs(v.Value.Examples) - } - case *openapi3.ResponseRef: - if v == nil { - return - } - v.Ref = "" - if v.Value != nil { - RemoveRefs(v.Value.Content) - RemoveRefs(v.Value.Headers) - } - case *openapi3.SchemaRef: - if v == nil { - return - } - v.Ref = "" - if v.Value != nil { - RemoveRefs(v.Value.Properties) - RemoveRefs(v.Value.Items) - RemoveRefs(v.Value.AllOf) - RemoveRefs(v.Value.AnyOf) - RemoveRefs(v.Value.OneOf) - RemoveRefs(v.Value.Not) - } - case *openapi3.HeaderRef: - if v == nil { - return - } - v.Ref = "" - if v.Value != nil { - RemoveRefs(v.Value.Parameter) - } - default: - //intentional panic, have covered all the types in kin-openapi v0.127.0 - //might fail in the future if new types are added, should be caught in tests - panic(fmt.Sprintf("unhandled type %v", target)) - } +func (c clearRefs) ProcessResponseRef(ref *openapi3.ResponseRef) { + ref.Ref = "" +} + +func (c clearRefs) ProcessSchemaRef(ref *openapi3.SchemaRef) { + ref.Ref = "" +} + +func (c clearRefs) ProcessSecuritySchemeRef(ref *openapi3.SecuritySchemeRef) { + ref.Ref = "" } diff --git a/internal/openapiwalker/walker.go b/internal/openapiwalker/walker.go new file mode 100644 index 00000000..a1a25787 --- /dev/null +++ b/internal/openapiwalker/walker.go @@ -0,0 +1,293 @@ +package openapiwalker + +import ( + "fmt" + + "github.com/getkin/kin-openapi/openapi3" +) + +type RefProcessor interface { + ProcessCallbackRef(ref *openapi3.CallbackRef) + ProcessExampleRef(ref *openapi3.ExampleRef) + ProcessHeaderRef(ref *openapi3.HeaderRef) + ProcessLinkRef(ref *openapi3.LinkRef) + ProcessParameterRef(ref *openapi3.ParameterRef) + ProcessRequestBodyRef(ref *openapi3.RequestBodyRef) + ProcessResponseRef(ref *openapi3.ResponseRef) + ProcessSchemaRef(ref *openapi3.SchemaRef) + ProcessSecuritySchemeRef(ref *openapi3.SecuritySchemeRef) +} + +// ProcessRefs visits all the documents and calls the RefProcessor for each ref encountered. +// +//nolint:gocyclo // needs to check each type in the kinopneapi lib +func ProcessRefs(data any, p RefProcessor) { + switch v := data.(type) { + case nil: + return + + case *openapi3.T: + if v != nil { + ProcessRefs(*v, p) + } + case *openapi3.Components: + if v != nil { + ProcessRefs(*v, p) + } + case *openapi3.MediaType: + if v != nil { + ProcessRefs(*v, p) + } + case *openapi3.Response: + if v != nil { + ProcessRefs(*v, p) + } + + case *openapi3.Parameter: + if v != nil { + ProcessRefs(*v, p) + } + case *openapi3.RequestBody: + if v != nil { + ProcessRefs(*v, p) + } + case openapi3.RequestBody: + ProcessRefs(v.Content, p) + + case openapi3.T: + ProcessRefs(v.Components, p) + ProcessRefs(v.Info, p) + ProcessRefs(v.Paths, p) + ProcessRefs(v.Security, p) + ProcessRefs(v.Servers, p) + ProcessRefs(v.Tags, p) + ProcessRefs(v.ExternalDocs, p) + case openapi3.Components: + ProcessRefs(v.Schemas, p) + ProcessRefs(v.Parameters, p) + ProcessRefs(v.Headers, p) + ProcessRefs(v.RequestBodies, p) + ProcessRefs(v.Responses, p) + ProcessRefs(v.SecuritySchemes, p) + ProcessRefs(v.Examples, p) + ProcessRefs(v.Links, p) + ProcessRefs(v.Callbacks, p) + + case openapi3.ResponseBodies: + for _, ref := range v { + ProcessRefs(ref, p) + } + + case openapi3.RequestBodies: + for _, ref := range v { + ProcessRefs(ref, p) + } + + case openapi3.SecurityRequirements: + for _, requirement := range v { + ProcessRefs(requirement, p) + } + + case openapi3.Response: + ProcessRefs(v.Headers, p) + ProcessRefs(v.Content, p) + ProcessRefs(v.Links, p) + + case openapi3.Links: + for _, link := range v { + ProcessRefs(link, p) + } + case openapi3.Content: + for _, mediaType := range v { + ProcessRefs(mediaType, p) + } + case openapi3.ParametersMap: + for _, ref := range v { + ProcessRefs(ref, p) + } + case openapi3.Schemas: + for _, schema := range v { + ProcessRefs(schema, p) + } + case openapi3.SchemaRefs: + for _, schema := range v { + ProcessRefs(schema, p) + } + case openapi3.Headers: + for _, header := range v { + ProcessRefs(header, p) + } + + case openapi3.MediaType: + ProcessRefs(v.Schema, p) + ProcessRefs(v.Examples, p) + + case openapi3.Parameter: + ProcessRefs(v.Schema, p) + ProcessRefs(v.Content, p) + ProcessRefs(v.Examples, p) + + case openapi3.Examples: + for _, example := range v { + ProcessRefs(example, p) + } + case *openapi3.Schema: + if v != nil { + ProcessRefs(*v, p) + } + case openapi3.SecuritySchemes: + for _, ref := range v { + ProcessRefs(ref, p) + } + case openapi3.Callbacks: + for _, ref := range v { + ProcessRefs(ref, p) + } + case *openapi3.Paths: + if v != nil { + ProcessRefs(*v, p) + } + case openapi3.Paths: + for _, path := range v.Map() { + ProcessRefs(path, p) + } + + case openapi3.Schema: + ProcessRefs(v.Properties, p) + ProcessRefs(v.Items, p) + ProcessRefs(v.AllOf, p) + ProcessRefs(v.AnyOf, p) + ProcessRefs(v.OneOf, p) + ProcessRefs(v.Not, p) + + case *openapi3.PathItem: + if v != nil { + ProcessRefs(*v, p) + } + case openapi3.PathItem: + ProcessRefs(v.Connect, p) + ProcessRefs(v.Delete, p) + ProcessRefs(v.Get, p) + ProcessRefs(v.Head, p) + ProcessRefs(v.Options, p) + ProcessRefs(v.Patch, p) + ProcessRefs(v.Post, p) + ProcessRefs(v.Put, p) + ProcessRefs(v.Trace, p) + ProcessRefs(v.Servers, p) + ProcessRefs(v.Parameters, p) + case *openapi3.Operation: + if v != nil { + ProcessRefs(*v, p) + } + case openapi3.Operation: + ProcessRefs(v.Parameters, p) + ProcessRefs(v.RequestBody, p) + ProcessRefs(v.Responses, p) + ProcessRefs(v.Callbacks, p) + ProcessRefs(v.Security, p) + ProcessRefs(v.Servers, p) + ProcessRefs(v.ExternalDocs, p) + case *openapi3.Responses: + if v != nil { + ProcessRefs(*v, p) + } + case openapi3.Responses: + for _, ref := range v.Map() { + ProcessRefs(ref, p) + } + case openapi3.Parameters: + for _, parameter := range v { + ProcessRefs(parameter, p) + } + case *openapi3.Callback: + if v != nil { + ProcessRefs(*v, p) + } + case openapi3.Callback: + for _, pathItem := range v.Map() { + ProcessRefs(pathItem, p) + } + case *openapi3.Example: + if v != nil { + ProcessRefs(*v, p) + } + case *openapi3.Header: + if v != nil { + ProcessRefs(*v, p) + } + case openapi3.Header: + ProcessRefs(v.Parameter, p) + + case *openapi3.CallbackRef: + if v != nil { + p.ProcessCallbackRef(v) + ProcessRefs(v.Value, p) + } + + case *openapi3.ExampleRef: + if v != nil { + p.ProcessExampleRef(v) + ProcessRefs(v.Value, p) + } + + case *openapi3.HeaderRef: + if v != nil { + p.ProcessHeaderRef(v) + ProcessRefs(v.Value, p) + } + case *openapi3.LinkRef: + if v != nil { + p.ProcessLinkRef(v) + ProcessRefs(v.Value, p) + } + case *openapi3.ParameterRef: + if v != nil { + p.ProcessParameterRef(v) + ProcessRefs(v.Value, p) + } + case *openapi3.RequestBodyRef: + if v != nil { + p.ProcessRequestBodyRef(v) + ProcessRefs(v.Value, p) + } + case *openapi3.ResponseRef: + if v != nil { + p.ProcessResponseRef(v) + ProcessRefs(v.Value, p) + } + + case *openapi3.SchemaRef: + if v != nil { + p.ProcessSchemaRef(v) + ProcessRefs(v.Value, p) + } + case *openapi3.SecuritySchemeRef: + if v != nil { + p.ProcessSecuritySchemeRef(v) + ProcessRefs(v.Value, p) + } + // no interesting nested fields + case *openapi3.Info: + case openapi3.Info: + case *openapi3.SecurityRequirements: + case *openapi3.SecurityRequirement: + case openapi3.SecurityRequirement: + case *openapi3.Servers: + case openapi3.Servers: + case openapi3.Server: + case *openapi3.ExternalDocs: + case openapi3.ExternalDocs: + case openapi3.Tags: + case openapi3.Tag: + case *openapi3.SecurityScheme: + case openapi3.SecurityScheme: + case openapi3.Example: + + default: + // intentional panic, have covered all the types in kin-openapi v0.127.0 + // might fail in the future if new types are added/types changed, should + // be caught in tests + panic(fmt.Sprintf("unhandled type %#v", v)) + } +} diff --git a/ref_alias_resolver.go b/ref_alias_resolver.go index 656e5cbe..3ac1fc3e 100644 --- a/ref_alias_resolver.go +++ b/ref_alias_resolver.go @@ -4,6 +4,8 @@ import ( "strings" "github.com/getkin/kin-openapi/openapi3" + + "github.com/snyk/vervet/v7/internal/openapiwalker" ) // refAliasResolver rewrites references in an OpenAPI document object to local @@ -13,6 +15,42 @@ type refAliasResolver struct { refAliases map[string]string } +func (l *refAliasResolver) ProcessCallbackRef(ref *openapi3.CallbackRef) { + ref.Ref = l.resolveRefAlias(ref.Ref) +} + +func (l *refAliasResolver) ProcessExampleRef(ref *openapi3.ExampleRef) { + ref.Ref = l.resolveRefAlias(ref.Ref) +} + +func (l *refAliasResolver) ProcessHeaderRef(ref *openapi3.HeaderRef) { + ref.Ref = l.resolveRefAlias(ref.Ref) +} + +func (l *refAliasResolver) ProcessLinkRef(ref *openapi3.LinkRef) { + ref.Ref = l.resolveRefAlias(ref.Ref) +} + +func (l *refAliasResolver) ProcessParameterRef(ref *openapi3.ParameterRef) { + ref.Ref = l.resolveRefAlias(ref.Ref) +} + +func (l *refAliasResolver) ProcessRequestBodyRef(ref *openapi3.RequestBodyRef) { + ref.Ref = l.resolveRefAlias(ref.Ref) +} + +func (l *refAliasResolver) ProcessResponseRef(ref *openapi3.ResponseRef) { + ref.Ref = l.resolveRefAlias(ref.Ref) +} + +func (l *refAliasResolver) ProcessSchemaRef(ref *openapi3.SchemaRef) { + ref.Ref = l.resolveRefAlias(ref.Ref) +} + +func (l *refAliasResolver) ProcessSecuritySchemeRef(ref *openapi3.SecuritySchemeRef) { + ref.Ref = l.resolveRefAlias(ref.Ref) +} + // newRefAliasResolver returns a new refAliasResolver. func newRefAliasResolver(doc *openapi3.T) *refAliasResolver { res := &refAliasResolver{doc: doc} @@ -49,25 +87,5 @@ func (l *refAliasResolver) resolveRefAlias(ref string) string { // resolve rewrites all references in the OpenAPI document to local references. func (l *refAliasResolver) resolve() { - for _, path := range l.doc.Paths.InMatchingOrder() { - for _, operation := range l.doc.Paths.Value(path).Operations() { - for _, parameter := range operation.Parameters { - parameter.Ref = l.resolveRefAlias(parameter.Ref) - } - if operation.RequestBody != nil { - operation.RequestBody.Ref = l.resolveRefAlias(operation.RequestBody.Ref) - } - for _, response := range operation.Responses.Map() { - response.Ref = l.resolveRefAlias(response.Ref) - if response.Value != nil { - for _, mediaType := range response.Value.Content { - mediaType.Schema.Ref = l.resolveRefAlias(mediaType.Schema.Ref) - for _, properties := range mediaType.Schema.Value.Properties { - properties.Ref = l.resolveRefAlias(properties.Ref) - } - } - } - } - } - } + openapiwalker.ProcessRefs(l.doc, l) } From 5f9da9be82a43a6f6bb4cce34336913128b1f4d7 Mon Sep 17 00:00:00 2001 From: Jatin Naik Date: Thu, 15 Aug 2024 15:42:02 +0100 Subject: [PATCH 5/6] chore: add test for ResolveRefsWithoutSourceName --- resource_test.go | 61 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/resource_test.go b/resource_test.go index d2f784c3..121347b0 100644 --- a/resource_test.go +++ b/resource_test.go @@ -2,6 +2,7 @@ package vervet_test import ( "context" + "net/url" "testing" "time" @@ -142,3 +143,63 @@ func TestResourceVersionsAtSunset(t *testing.T) { } } } + +func TestResolveRefsWithoutSourceName(t *testing.T) { + tests := []struct { + name string + ref string + want string + }{ + { + name: "empty ref", + ref: "", + want: "", + }, + { + name: "ref with source and fragment", + ref: "#/components/schemas/Pet", + want: "Pet", + }, + { + name: "ref without source", + ref: "components/schemas/Pet", + want: "Pet", + }, + { + name: "ref with extension", + ref: "models/Pet.yaml", + want: "Pet", + }, + { + name: "ref with multiple extensions", + ref: "models/Pet.json.gz", + want: "Pet", + }, + { + name: "ref with complex path", + ref: "path/to/models/Pet.yaml", + want: "Pet", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := ResolveRefsWithoutSourceName(nil, mockComponentRef(tt.ref)); got != tt.want { + t.Errorf("ResolveRefsWithoutSourceName() = %v, want %v", got, tt.want) + } + }) + } +} + +type mockComponentRef string + +func (m mockComponentRef) RefString() string { + return string(m) +} + +func (m mockComponentRef) RefPath() *url.URL { + return nil +} + +func (m mockComponentRef) CollectionName() string { + return "" +} From 0c7693b35a562ca90d3102bf63a0f9da58ec304a Mon Sep 17 00:00:00 2001 From: Jatin Naik Date: Fri, 16 Aug 2024 08:43:19 +0100 Subject: [PATCH 6/6] feat!: upgrade to kin-openapi 0.127 kin-openapi has breaking changes to a number of underlying structs --- cmd/vervet/main.go | 2 +- cmd/vu-api/main.go | 12 ++++++------ cmd/vu-scraper/main.go | 12 ++++++------ collator_test.go | 4 ++-- config/config_test.go | 2 +- config/underground.go | 2 +- config/underground_test.go | 4 ++-- document_test.go | 4 ++-- generate/generate.go | 4 ++-- generate/generate_test.go | 4 ++-- go.mod | 2 +- include_headers_test.go | 4 ++-- inliner.go | 2 +- internal/backstage/backstage.go | 2 +- internal/backstage/backstage_test.go | 2 +- internal/cmd/backstage.go | 4 ++-- internal/cmd/compiler.go | 8 ++++---- internal/cmd/compiler_test.go | 6 +++--- internal/cmd/filter.go | 2 +- internal/cmd/filter_test.go | 6 +++--- internal/cmd/generate.go | 2 +- internal/cmd/localize.go | 2 +- internal/cmd/resolve.go | 2 +- internal/cmd/resource.go | 6 +++--- internal/cmd/resource_test.go | 4 ++-- internal/cmd/scaffold.go | 2 +- internal/cmd/scaffold_test.go | 4 ++-- internal/compiler/compiler.go | 6 +++--- internal/compiler/compiler_test.go | 6 +++--- internal/files/files.go | 4 ++-- internal/generator/generator.go | 4 ++-- internal/generator/generator_test.go | 4 ++-- internal/generator/resources.go | 6 +++--- internal/handler/handler.go | 8 ++++---- internal/handler/handler_test.go | 6 +++--- internal/scaffold/scaffold.go | 2 +- internal/scaffold/scaffold_test.go | 4 ++-- internal/scraper/gcs_scraper_test.go | 8 ++++---- internal/scraper/metrics_test.go | 4 ++-- internal/scraper/s3_scraper_test.go | 8 ++++---- internal/scraper/scraper.go | 4 ++-- internal/scraper/scraper_test.go | 6 +++--- internal/simplebuild/build.go | 6 +++--- internal/simplebuild/build_test.go | 4 ++-- internal/simplebuild/output.go | 8 ++++---- internal/simplebuild/output_test.go | 4 ++-- internal/simplebuild/overlays.go | 4 ++-- internal/simplebuild/refs_test.go | 2 +- internal/storage/collator.go | 2 +- internal/storage/collator_test.go | 6 +++--- internal/storage/disk/disk.go | 4 ++-- internal/storage/disk/disk_test.go | 2 +- internal/storage/gcs/client.go | 4 ++-- internal/storage/gcs/client_test.go | 6 +++--- internal/storage/gcs/testing/testing.go | 2 +- internal/storage/revision.go | 2 +- internal/storage/revision_test.go | 4 ++-- internal/storage/s3/client.go | 4 ++-- internal/storage/s3/client_test.go | 6 +++--- internal/storage/s3/testing/testing.go | 2 +- internal/storage/storage.go | 2 +- merge_test.go | 4 ++-- ref_alias_resolver.go | 2 +- ref_alias_resolver_test.go | 4 ++-- ref_index_test.go | 4 ++-- remove_elements_test.go | 4 ++-- resource_test.go | 4 ++-- spec_test.go | 4 ++-- util_test.go | 4 ++-- version_test.go | 2 +- versionware/handler.go | 2 +- versionware/handler_test.go | 4 ++-- versionware/validator.go | 2 +- versionware/validator_test.go | 2 +- 74 files changed, 153 insertions(+), 153 deletions(-) diff --git a/cmd/vervet/main.go b/cmd/vervet/main.go index 16c5e950..d0a78745 100644 --- a/cmd/vervet/main.go +++ b/cmd/vervet/main.go @@ -4,7 +4,7 @@ import ( "log" "os" - "github.com/snyk/vervet/v7/internal/cmd" + "github.com/snyk/vervet/v8/internal/cmd" ) func main() { diff --git a/cmd/vu-api/main.go b/cmd/vu-api/main.go index 53537b74..0777a526 100644 --- a/cmd/vu-api/main.go +++ b/cmd/vu-api/main.go @@ -15,12 +15,12 @@ import ( "github.com/rs/zerolog/log" "golang.org/x/sync/errgroup" - "github.com/snyk/vervet/v7/config" - "github.com/snyk/vervet/v7/internal/handler" - "github.com/snyk/vervet/v7/internal/storage" - "github.com/snyk/vervet/v7/internal/storage/disk" - "github.com/snyk/vervet/v7/internal/storage/gcs" - "github.com/snyk/vervet/v7/internal/storage/s3" + "github.com/snyk/vervet/v8/config" + "github.com/snyk/vervet/v8/internal/handler" + "github.com/snyk/vervet/v8/internal/storage" + "github.com/snyk/vervet/v8/internal/storage/disk" + "github.com/snyk/vervet/v8/internal/storage/gcs" + "github.com/snyk/vervet/v8/internal/storage/s3" ) func main() { diff --git a/cmd/vu-scraper/main.go b/cmd/vu-scraper/main.go index ec746282..77520ce2 100644 --- a/cmd/vu-scraper/main.go +++ b/cmd/vu-scraper/main.go @@ -11,12 +11,12 @@ import ( "github.com/rs/zerolog" "github.com/rs/zerolog/log" - "github.com/snyk/vervet/v7/config" - "github.com/snyk/vervet/v7/internal/scraper" - "github.com/snyk/vervet/v7/internal/storage" - "github.com/snyk/vervet/v7/internal/storage/disk" - "github.com/snyk/vervet/v7/internal/storage/gcs" - "github.com/snyk/vervet/v7/internal/storage/s3" + "github.com/snyk/vervet/v8/config" + "github.com/snyk/vervet/v8/internal/scraper" + "github.com/snyk/vervet/v8/internal/storage" + "github.com/snyk/vervet/v8/internal/storage/disk" + "github.com/snyk/vervet/v8/internal/storage/gcs" + "github.com/snyk/vervet/v8/internal/storage/s3" ) func main() { diff --git a/collator_test.go b/collator_test.go index 52ed2886..260a9fc2 100644 --- a/collator_test.go +++ b/collator_test.go @@ -5,8 +5,8 @@ import ( qt "github.com/frankban/quicktest" - "github.com/snyk/vervet/v7" - "github.com/snyk/vervet/v7/testdata" + "github.com/snyk/vervet/v8" + "github.com/snyk/vervet/v8/testdata" ) func TestRefRemover(t *testing.T) { diff --git a/config/config_test.go b/config/config_test.go index 609ce845..e692c7fe 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -6,7 +6,7 @@ import ( qt "github.com/frankban/quicktest" - "github.com/snyk/vervet/v7/config" + "github.com/snyk/vervet/v8/config" ) func TestLoad(t *testing.T) { diff --git a/config/underground.go b/config/underground.go index d4393bea..16fcf02f 100644 --- a/config/underground.go +++ b/config/underground.go @@ -7,7 +7,7 @@ import ( "github.com/spf13/viper" - "github.com/snyk/vervet/v7" + "github.com/snyk/vervet/v8" ) // StorageType describes backend implementations supported by Vervet Underground. diff --git a/config/underground_test.go b/config/underground_test.go index 08123951..f3d6330a 100644 --- a/config/underground_test.go +++ b/config/underground_test.go @@ -6,8 +6,8 @@ import ( qt "github.com/frankban/quicktest" - "github.com/snyk/vervet/v7" - "github.com/snyk/vervet/v7/config" + "github.com/snyk/vervet/v8" + "github.com/snyk/vervet/v8/config" ) func createTestFile(c *qt.C, data []byte) *os.File { diff --git a/document_test.go b/document_test.go index d59bbdf3..fbf63319 100644 --- a/document_test.go +++ b/document_test.go @@ -6,8 +6,8 @@ import ( qt "github.com/frankban/quicktest" - "github.com/snyk/vervet/v7" - "github.com/snyk/vervet/v7/testdata" + "github.com/snyk/vervet/v8" + "github.com/snyk/vervet/v8/testdata" ) func TestNewDocumentFile(t *testing.T) { diff --git a/generate/generate.go b/generate/generate.go index fa82fa5f..32802efe 100644 --- a/generate/generate.go +++ b/generate/generate.go @@ -8,8 +8,8 @@ import ( "strings" "text/template" - "github.com/snyk/vervet/v7/config" - "github.com/snyk/vervet/v7/internal/generator" + "github.com/snyk/vervet/v8/config" + "github.com/snyk/vervet/v8/internal/generator" ) // GeneratorParams contains the metadata needed to execute code generators. diff --git a/generate/generate_test.go b/generate/generate_test.go index ec6a23cb..cb7d9158 100644 --- a/generate/generate_test.go +++ b/generate/generate_test.go @@ -8,8 +8,8 @@ import ( qt "github.com/frankban/quicktest" - "github.com/snyk/vervet/v7/generate" - "github.com/snyk/vervet/v7/testdata" + "github.com/snyk/vervet/v8/generate" + "github.com/snyk/vervet/v8/testdata" ) func TestGenerateFS(t *testing.T) { diff --git a/go.mod b/go.mod index 67ff2bbb..e69ad7b6 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/snyk/vervet/v7 +module github.com/snyk/vervet/v8 go 1.22 diff --git a/include_headers_test.go b/include_headers_test.go index a6534fa0..84408520 100644 --- a/include_headers_test.go +++ b/include_headers_test.go @@ -6,8 +6,8 @@ import ( qt "github.com/frankban/quicktest" - "github.com/snyk/vervet/v7" - "github.com/snyk/vervet/v7/testdata" + "github.com/snyk/vervet/v8" + "github.com/snyk/vervet/v8/testdata" ) func TestCommonResponseHeaders(t *testing.T) { diff --git a/inliner.go b/inliner.go index 3ced6b6a..1b329472 100644 --- a/inliner.go +++ b/inliner.go @@ -3,7 +3,7 @@ package vervet import ( "github.com/getkin/kin-openapi/openapi3" - "github.com/snyk/vervet/v7/internal/openapiwalker" + "github.com/snyk/vervet/v8/internal/openapiwalker" ) // Inliner inlines the component. diff --git a/internal/backstage/backstage.go b/internal/backstage/backstage.go index 996b3916..8075f9e4 100644 --- a/internal/backstage/backstage.go +++ b/internal/backstage/backstage.go @@ -16,7 +16,7 @@ import ( "github.com/vmware-labs/yaml-jsonpath/pkg/yamlpath" "gopkg.in/yaml.v3" - "github.com/snyk/vervet/v7" + "github.com/snyk/vervet/v8" ) const ( diff --git a/internal/backstage/backstage_test.go b/internal/backstage/backstage_test.go index 857779f4..52f0e3d0 100644 --- a/internal/backstage/backstage_test.go +++ b/internal/backstage/backstage_test.go @@ -7,7 +7,7 @@ import ( qt "github.com/frankban/quicktest" - "github.com/snyk/vervet/v7/testdata" + "github.com/snyk/vervet/v8/testdata" ) func TestBackstageName(t *testing.T) { diff --git a/internal/cmd/backstage.go b/internal/cmd/backstage.go index e82ce1e4..4069e405 100644 --- a/internal/cmd/backstage.go +++ b/internal/cmd/backstage.go @@ -11,8 +11,8 @@ import ( "github.com/urfave/cli/v2" - "github.com/snyk/vervet/v7/config" - "github.com/snyk/vervet/v7/internal/backstage" + "github.com/snyk/vervet/v8/config" + "github.com/snyk/vervet/v8/internal/backstage" ) // BackstageCommand is the `vervet backstage` subcommand. diff --git a/internal/cmd/compiler.go b/internal/cmd/compiler.go index c228dc7f..ece748fc 100644 --- a/internal/cmd/compiler.go +++ b/internal/cmd/compiler.go @@ -6,10 +6,10 @@ import ( "github.com/urfave/cli/v2" - "github.com/snyk/vervet/v7" - "github.com/snyk/vervet/v7/config" - "github.com/snyk/vervet/v7/internal/compiler" - "github.com/snyk/vervet/v7/internal/simplebuild" + "github.com/snyk/vervet/v8" + "github.com/snyk/vervet/v8/config" + "github.com/snyk/vervet/v8/internal/compiler" + "github.com/snyk/vervet/v8/internal/simplebuild" ) var defaultPivotDate = vervet.MustParseVersion("2024-09-01") diff --git a/internal/cmd/compiler_test.go b/internal/cmd/compiler_test.go index 74eb48ee..729f96da 100644 --- a/internal/cmd/compiler_test.go +++ b/internal/cmd/compiler_test.go @@ -8,9 +8,9 @@ import ( qt "github.com/frankban/quicktest" "github.com/getkin/kin-openapi/openapi3" - "github.com/snyk/vervet/v7" - "github.com/snyk/vervet/v7/internal/cmd" - "github.com/snyk/vervet/v7/testdata" + "github.com/snyk/vervet/v8" + "github.com/snyk/vervet/v8/internal/cmd" + "github.com/snyk/vervet/v8/testdata" ) var specFile = "/spec.yaml" diff --git a/internal/cmd/filter.go b/internal/cmd/filter.go index e2b5cec7..357ae19c 100644 --- a/internal/cmd/filter.go +++ b/internal/cmd/filter.go @@ -6,7 +6,7 @@ import ( "github.com/getkin/kin-openapi/openapi3" "github.com/urfave/cli/v2" - "github.com/snyk/vervet/v7" + "github.com/snyk/vervet/v8" ) // FilterCommand is the `vervet filter` subcommand. diff --git a/internal/cmd/filter_test.go b/internal/cmd/filter_test.go index 719ad984..2c84d445 100644 --- a/internal/cmd/filter_test.go +++ b/internal/cmd/filter_test.go @@ -6,9 +6,9 @@ import ( qt "github.com/frankban/quicktest" - "github.com/snyk/vervet/v7" - "github.com/snyk/vervet/v7/internal/cmd" - "github.com/snyk/vervet/v7/testdata" + "github.com/snyk/vervet/v8" + "github.com/snyk/vervet/v8/internal/cmd" + "github.com/snyk/vervet/v8/testdata" ) func TestFilterInclude(t *testing.T) { diff --git a/internal/cmd/generate.go b/internal/cmd/generate.go index 94f92d73..1d4d914c 100644 --- a/internal/cmd/generate.go +++ b/internal/cmd/generate.go @@ -5,7 +5,7 @@ import ( "github.com/urfave/cli/v2" - "github.com/snyk/vervet/v7/generate" + "github.com/snyk/vervet/v8/generate" ) // GenerateCommand is the `vervet generate` subcommand. diff --git a/internal/cmd/localize.go b/internal/cmd/localize.go index 5a0f2527..6ce9932c 100644 --- a/internal/cmd/localize.go +++ b/internal/cmd/localize.go @@ -5,7 +5,7 @@ import ( "github.com/urfave/cli/v2" - "github.com/snyk/vervet/v7" + "github.com/snyk/vervet/v8" ) // LocalizeCommand is the `vervet localize` subcommand. diff --git a/internal/cmd/resolve.go b/internal/cmd/resolve.go index f5f5ae2a..2fe1d3d1 100644 --- a/internal/cmd/resolve.go +++ b/internal/cmd/resolve.go @@ -5,7 +5,7 @@ import ( "github.com/urfave/cli/v2" - "github.com/snyk/vervet/v7" + "github.com/snyk/vervet/v8" ) // ResolveCommand is the `vervet resolve` subcommand. diff --git a/internal/cmd/resource.go b/internal/cmd/resource.go index b2c049f7..f6853280 100644 --- a/internal/cmd/resource.go +++ b/internal/cmd/resource.go @@ -9,9 +9,9 @@ import ( "github.com/olekukonko/tablewriter" "github.com/urfave/cli/v2" - "github.com/snyk/vervet/v7" - "github.com/snyk/vervet/v7/config" - "github.com/snyk/vervet/v7/internal/compiler" + "github.com/snyk/vervet/v8" + "github.com/snyk/vervet/v8/config" + "github.com/snyk/vervet/v8/internal/compiler" ) // ResourceCommand is the `vervet resource` subcommand. diff --git a/internal/cmd/resource_test.go b/internal/cmd/resource_test.go index 798e0b30..cc1e677e 100644 --- a/internal/cmd/resource_test.go +++ b/internal/cmd/resource_test.go @@ -7,8 +7,8 @@ import ( qt "github.com/frankban/quicktest" - "github.com/snyk/vervet/v7/internal/cmd" - "github.com/snyk/vervet/v7/testdata" + "github.com/snyk/vervet/v8/internal/cmd" + "github.com/snyk/vervet/v8/testdata" ) func cd(c *qt.C, path string) { diff --git a/internal/cmd/scaffold.go b/internal/cmd/scaffold.go index eb3f67f9..eae47a2a 100644 --- a/internal/cmd/scaffold.go +++ b/internal/cmd/scaffold.go @@ -7,7 +7,7 @@ import ( "github.com/urfave/cli/v2" - "github.com/snyk/vervet/v7/internal/scaffold" + "github.com/snyk/vervet/v8/internal/scaffold" ) // Scaffold is the `vervet scaffold` subcommand. diff --git a/internal/cmd/scaffold_test.go b/internal/cmd/scaffold_test.go index cd7b7e96..879c9585 100644 --- a/internal/cmd/scaffold_test.go +++ b/internal/cmd/scaffold_test.go @@ -8,8 +8,8 @@ import ( qt "github.com/frankban/quicktest" "github.com/urfave/cli/v2" - "github.com/snyk/vervet/v7/internal/cmd" - "github.com/snyk/vervet/v7/testdata" + "github.com/snyk/vervet/v8/internal/cmd" + "github.com/snyk/vervet/v8/testdata" ) var vervetConfigFile = "./.vervet.yaml" diff --git a/internal/compiler/compiler.go b/internal/compiler/compiler.go index 8e4faba0..be4bbeb3 100644 --- a/internal/compiler/compiler.go +++ b/internal/compiler/compiler.go @@ -13,9 +13,9 @@ import ( "github.com/ghodss/yaml" "go.uber.org/multierr" - "github.com/snyk/vervet/v7" - "github.com/snyk/vervet/v7/config" - "github.com/snyk/vervet/v7/internal/files" + "github.com/snyk/vervet/v8" + "github.com/snyk/vervet/v8/config" + "github.com/snyk/vervet/v8/internal/files" ) // A Compiler checks and builds versioned API resource inputs into aggregated diff --git a/internal/compiler/compiler_test.go b/internal/compiler/compiler_test.go index e62f1e2a..4deb16cd 100644 --- a/internal/compiler/compiler_test.go +++ b/internal/compiler/compiler_test.go @@ -11,9 +11,9 @@ import ( qt "github.com/frankban/quicktest" - "github.com/snyk/vervet/v7" - "github.com/snyk/vervet/v7/config" - "github.com/snyk/vervet/v7/testdata" + "github.com/snyk/vervet/v8" + "github.com/snyk/vervet/v8/config" + "github.com/snyk/vervet/v8/testdata" ) func setup(c *qt.C) { diff --git a/internal/files/files.go b/internal/files/files.go index 0f25af5a..ef6d504b 100644 --- a/internal/files/files.go +++ b/internal/files/files.go @@ -7,8 +7,8 @@ import ( "github.com/bmatcuk/doublestar/v4" - "github.com/snyk/vervet/v7" - "github.com/snyk/vervet/v7/config" + "github.com/snyk/vervet/v8" + "github.com/snyk/vervet/v8/config" ) // FileSource defines a source of spec files to lint. This abstraction allows diff --git a/internal/generator/generator.go b/internal/generator/generator.go index 8cbd545f..bd4ca288 100644 --- a/internal/generator/generator.go +++ b/internal/generator/generator.go @@ -13,8 +13,8 @@ import ( "github.com/ghodss/yaml" - "github.com/snyk/vervet/v7" - "github.com/snyk/vervet/v7/config" + "github.com/snyk/vervet/v8" + "github.com/snyk/vervet/v8/config" ) // Generator generates files for new resources from data models and templates. diff --git a/internal/generator/generator_test.go b/internal/generator/generator_test.go index 34b1bd65..637a1cf8 100644 --- a/internal/generator/generator_test.go +++ b/internal/generator/generator_test.go @@ -9,8 +9,8 @@ import ( qt "github.com/frankban/quicktest" - "github.com/snyk/vervet/v7/config" - "github.com/snyk/vervet/v7/testdata" + "github.com/snyk/vervet/v8/config" + "github.com/snyk/vervet/v8/testdata" ) func setup(c *qt.C) { diff --git a/internal/generator/resources.go b/internal/generator/resources.go index b0fd9553..3fc2ff5c 100644 --- a/internal/generator/resources.go +++ b/internal/generator/resources.go @@ -5,9 +5,9 @@ import ( "github.com/getkin/kin-openapi/openapi3" - "github.com/snyk/vervet/v7" - "github.com/snyk/vervet/v7/config" - "github.com/snyk/vervet/v7/internal/compiler" + "github.com/snyk/vervet/v8" + "github.com/snyk/vervet/v8/config" + "github.com/snyk/vervet/v8/internal/compiler" ) // ResourceKey uniquely identifies an API resource. diff --git a/internal/handler/handler.go b/internal/handler/handler.go index bb97b8d3..5e81a226 100644 --- a/internal/handler/handler.go +++ b/internal/handler/handler.go @@ -16,10 +16,10 @@ import ( prommiddleware "github.com/slok/go-http-metrics/middleware" prommiddlewarestd "github.com/slok/go-http-metrics/middleware/std" - "github.com/snyk/vervet/v7" - "github.com/snyk/vervet/v7/config" - "github.com/snyk/vervet/v7/internal/storage" - "github.com/snyk/vervet/v7/versionware" + "github.com/snyk/vervet/v8" + "github.com/snyk/vervet/v8/config" + "github.com/snyk/vervet/v8/internal/storage" + "github.com/snyk/vervet/v8/versionware" ) // Handler handles Vervet Underground HTTP requests. diff --git a/internal/handler/handler_test.go b/internal/handler/handler_test.go index 58bba9ed..0170023a 100644 --- a/internal/handler/handler_test.go +++ b/internal/handler/handler_test.go @@ -9,9 +9,9 @@ import ( qt "github.com/frankban/quicktest" - "github.com/snyk/vervet/v7" - "github.com/snyk/vervet/v7/config" - "github.com/snyk/vervet/v7/internal/handler" + "github.com/snyk/vervet/v8" + "github.com/snyk/vervet/v8/config" + "github.com/snyk/vervet/v8/internal/handler" ) func TestHealth(t *testing.T) { diff --git a/internal/scaffold/scaffold.go b/internal/scaffold/scaffold.go index 312e756a..d37ac158 100644 --- a/internal/scaffold/scaffold.go +++ b/internal/scaffold/scaffold.go @@ -8,7 +8,7 @@ import ( "github.com/ghodss/yaml" - "github.com/snyk/vervet/v7/internal/files" + "github.com/snyk/vervet/v8/internal/files" ) // ErrAlreadyInitialized is used when scaffolding is being run on a project that is already setup. diff --git a/internal/scaffold/scaffold_test.go b/internal/scaffold/scaffold_test.go index 4e0d1889..128eae92 100644 --- a/internal/scaffold/scaffold_test.go +++ b/internal/scaffold/scaffold_test.go @@ -7,8 +7,8 @@ import ( qt "github.com/frankban/quicktest" - "github.com/snyk/vervet/v7/internal/scaffold" - "github.com/snyk/vervet/v7/testdata" + "github.com/snyk/vervet/v8/internal/scaffold" + "github.com/snyk/vervet/v8/testdata" ) func TestScaffold(t *testing.T) { diff --git a/internal/scraper/gcs_scraper_test.go b/internal/scraper/gcs_scraper_test.go index 1732c8d1..81d9364c 100644 --- a/internal/scraper/gcs_scraper_test.go +++ b/internal/scraper/gcs_scraper_test.go @@ -9,10 +9,10 @@ import ( qt "github.com/frankban/quicktest" "github.com/getkin/kin-openapi/openapi3" - "github.com/snyk/vervet/v7/config" - "github.com/snyk/vervet/v7/internal/scraper" - "github.com/snyk/vervet/v7/internal/storage/gcs" - gcstesting "github.com/snyk/vervet/v7/internal/storage/gcs/testing" + "github.com/snyk/vervet/v8/config" + "github.com/snyk/vervet/v8/internal/scraper" + "github.com/snyk/vervet/v8/internal/storage/gcs" + gcstesting "github.com/snyk/vervet/v8/internal/storage/gcs/testing" ) func TestGCSScraper(t *testing.T) { diff --git a/internal/scraper/metrics_test.go b/internal/scraper/metrics_test.go index e373c0b6..9d4ff988 100644 --- a/internal/scraper/metrics_test.go +++ b/internal/scraper/metrics_test.go @@ -8,8 +8,8 @@ import ( qt "github.com/frankban/quicktest" "github.com/prometheus/client_golang/prometheus" - "github.com/snyk/vervet/v7/internal/scraper" - "github.com/snyk/vervet/v7/internal/testutil" + "github.com/snyk/vervet/v8/internal/scraper" + "github.com/snyk/vervet/v8/internal/testutil" ) type mockRoundTripper struct { diff --git a/internal/scraper/s3_scraper_test.go b/internal/scraper/s3_scraper_test.go index a9407081..b57205ab 100644 --- a/internal/scraper/s3_scraper_test.go +++ b/internal/scraper/s3_scraper_test.go @@ -9,10 +9,10 @@ import ( qt "github.com/frankban/quicktest" "github.com/getkin/kin-openapi/openapi3" - "github.com/snyk/vervet/v7/config" - "github.com/snyk/vervet/v7/internal/scraper" - "github.com/snyk/vervet/v7/internal/storage/s3" - s3testing "github.com/snyk/vervet/v7/internal/storage/s3/testing" + "github.com/snyk/vervet/v8/config" + "github.com/snyk/vervet/v8/internal/scraper" + "github.com/snyk/vervet/v8/internal/storage/s3" + s3testing "github.com/snyk/vervet/v8/internal/storage/s3/testing" ) func TestS3Scraper(t *testing.T) { diff --git a/internal/scraper/scraper.go b/internal/scraper/scraper.go index a1e85375..89f83408 100644 --- a/internal/scraper/scraper.go +++ b/internal/scraper/scraper.go @@ -16,8 +16,8 @@ import ( "github.com/rs/zerolog/log" "go.uber.org/multierr" - "github.com/snyk/vervet/v7/config" - "github.com/snyk/vervet/v7/internal/storage" + "github.com/snyk/vervet/v8/config" + "github.com/snyk/vervet/v8/internal/storage" ) // Scraper gets OpenAPI specs from a collection of services and updates storage diff --git a/internal/scraper/scraper_test.go b/internal/scraper/scraper_test.go index f79b3a25..af406916 100644 --- a/internal/scraper/scraper_test.go +++ b/internal/scraper/scraper_test.go @@ -14,9 +14,9 @@ import ( "github.com/gorilla/mux" "github.com/rs/zerolog/log" - "github.com/snyk/vervet/v7/config" - "github.com/snyk/vervet/v7/internal/scraper" - "github.com/snyk/vervet/v7/internal/storage/disk" + "github.com/snyk/vervet/v8/config" + "github.com/snyk/vervet/v8/internal/scraper" + "github.com/snyk/vervet/v8/internal/storage/disk" ) var ( diff --git a/internal/simplebuild/build.go b/internal/simplebuild/build.go index 688c0ea7..9b80bf2c 100644 --- a/internal/simplebuild/build.go +++ b/internal/simplebuild/build.go @@ -9,9 +9,9 @@ import ( "github.com/getkin/kin-openapi/openapi3" - "github.com/snyk/vervet/v7" - "github.com/snyk/vervet/v7/config" - "github.com/snyk/vervet/v7/internal/files" + "github.com/snyk/vervet/v8" + "github.com/snyk/vervet/v8/config" + "github.com/snyk/vervet/v8/internal/files" ) // Build compiles the versioned resources in a project configuration based on diff --git a/internal/simplebuild/build_test.go b/internal/simplebuild/build_test.go index 083853b7..c8fc328d 100644 --- a/internal/simplebuild/build_test.go +++ b/internal/simplebuild/build_test.go @@ -8,8 +8,8 @@ import ( qt "github.com/frankban/quicktest" "github.com/getkin/kin-openapi/openapi3" - "github.com/snyk/vervet/v7" - "github.com/snyk/vervet/v7/internal/simplebuild" + "github.com/snyk/vervet/v8" + "github.com/snyk/vervet/v8/internal/simplebuild" ) func TestGetLatest(t *testing.T) { diff --git a/internal/simplebuild/output.go b/internal/simplebuild/output.go index 00bb2e8e..7b5cd7af 100644 --- a/internal/simplebuild/output.go +++ b/internal/simplebuild/output.go @@ -11,10 +11,10 @@ import ( "github.com/ghodss/yaml" - "github.com/snyk/vervet/v7" - "github.com/snyk/vervet/v7/config" - "github.com/snyk/vervet/v7/internal/compiler" - "github.com/snyk/vervet/v7/internal/files" + "github.com/snyk/vervet/v8" + "github.com/snyk/vervet/v8/config" + "github.com/snyk/vervet/v8/internal/compiler" + "github.com/snyk/vervet/v8/internal/files" ) // Some services have a need to write specs to multiple destinations. This diff --git a/internal/simplebuild/output_test.go b/internal/simplebuild/output_test.go index 9afef9b8..45dfd08b 100644 --- a/internal/simplebuild/output_test.go +++ b/internal/simplebuild/output_test.go @@ -9,8 +9,8 @@ import ( qt "github.com/frankban/quicktest" "github.com/getkin/kin-openapi/openapi3" - "github.com/snyk/vervet/v7" - "github.com/snyk/vervet/v7/config" + "github.com/snyk/vervet/v8" + "github.com/snyk/vervet/v8/config" ) func TestDocSet_WriteOutputs(t *testing.T) { diff --git a/internal/simplebuild/overlays.go b/internal/simplebuild/overlays.go index 23d6d51d..b3e504de 100644 --- a/internal/simplebuild/overlays.go +++ b/internal/simplebuild/overlays.go @@ -7,8 +7,8 @@ import ( "github.com/getkin/kin-openapi/openapi3" - "github.com/snyk/vervet/v7" - "github.com/snyk/vervet/v7/config" + "github.com/snyk/vervet/v8" + "github.com/snyk/vervet/v8/config" ) func (docs DocSet) ApplyOverlays(ctx context.Context, cfgs []*config.Overlay) error { diff --git a/internal/simplebuild/refs_test.go b/internal/simplebuild/refs_test.go index 226ec114..bd41d69e 100644 --- a/internal/simplebuild/refs_test.go +++ b/internal/simplebuild/refs_test.go @@ -6,7 +6,7 @@ import ( qt "github.com/frankban/quicktest" "github.com/getkin/kin-openapi/openapi3" - "github.com/snyk/vervet/v7/internal/simplebuild" + "github.com/snyk/vervet/v8/internal/simplebuild" ) func TestResolveRefs(t *testing.T) { diff --git a/internal/storage/collator.go b/internal/storage/collator.go index d0ac31ed..824ff8d7 100644 --- a/internal/storage/collator.go +++ b/internal/storage/collator.go @@ -8,7 +8,7 @@ import ( "github.com/getkin/kin-openapi/openapi3" "github.com/rs/zerolog/log" - "github.com/snyk/vervet/v7" + "github.com/snyk/vervet/v8" ) // Collator is an aggregate of service specs and uniqueVersions scraped by VU. It diff --git a/internal/storage/collator_test.go b/internal/storage/collator_test.go index 05634bd1..c501c68f 100644 --- a/internal/storage/collator_test.go +++ b/internal/storage/collator_test.go @@ -7,9 +7,9 @@ import ( qt "github.com/frankban/quicktest" - "github.com/snyk/vervet/v7" - "github.com/snyk/vervet/v7/internal/storage" - "github.com/snyk/vervet/v7/testdata" + "github.com/snyk/vervet/v8" + "github.com/snyk/vervet/v8/internal/storage" + "github.com/snyk/vervet/v8/testdata" ) const serviceASpec = ` diff --git a/internal/storage/disk/disk.go b/internal/storage/disk/disk.go index 911c6fb6..f1419ec9 100644 --- a/internal/storage/disk/disk.go +++ b/internal/storage/disk/disk.go @@ -17,8 +17,8 @@ import ( "github.com/getkin/kin-openapi/openapi3" - "github.com/snyk/vervet/v7" - "github.com/snyk/vervet/v7/internal/storage" + "github.com/snyk/vervet/v8" + "github.com/snyk/vervet/v8/internal/storage" ) type Storage struct { diff --git a/internal/storage/disk/disk_test.go b/internal/storage/disk/disk_test.go index 8c9d2e7b..2198953a 100644 --- a/internal/storage/disk/disk_test.go +++ b/internal/storage/disk/disk_test.go @@ -8,7 +8,7 @@ import ( qt "github.com/frankban/quicktest" - "github.com/snyk/vervet/v7/internal/storage" + "github.com/snyk/vervet/v8/internal/storage" ) var t0 = time.Date(2021, time.December, 3, 20, 49, 51, 0, time.UTC) diff --git a/internal/storage/gcs/client.go b/internal/storage/gcs/client.go index 1cb9ec65..640ea4e5 100644 --- a/internal/storage/gcs/client.go +++ b/internal/storage/gcs/client.go @@ -16,8 +16,8 @@ import ( "google.golang.org/api/iterator" "google.golang.org/api/option" - "github.com/snyk/vervet/v7" - vustorage "github.com/snyk/vervet/v7/internal/storage" + "github.com/snyk/vervet/v8" + vustorage "github.com/snyk/vervet/v8/internal/storage" ) // StaticKeyCredentials structure google.Credentials for diff --git a/internal/storage/gcs/client_test.go b/internal/storage/gcs/client_test.go index 50a84140..ed6d2aff 100644 --- a/internal/storage/gcs/client_test.go +++ b/internal/storage/gcs/client_test.go @@ -7,9 +7,9 @@ import ( qt "github.com/frankban/quicktest" - "github.com/snyk/vervet/v7/internal/storage" - "github.com/snyk/vervet/v7/internal/storage/gcs" - gcstesting "github.com/snyk/vervet/v7/internal/storage/gcs/testing" + "github.com/snyk/vervet/v8/internal/storage" + "github.com/snyk/vervet/v8/internal/storage/gcs" + gcstesting "github.com/snyk/vervet/v8/internal/storage/gcs/testing" ) var specFile = "spec.txt" diff --git a/internal/storage/gcs/testing/testing.go b/internal/storage/gcs/testing/testing.go index 3c816a23..1baced9d 100644 --- a/internal/storage/gcs/testing/testing.go +++ b/internal/storage/gcs/testing/testing.go @@ -16,7 +16,7 @@ import ( "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" - "github.com/snyk/vervet/v7/internal/storage/gcs" + "github.com/snyk/vervet/v8/internal/storage/gcs" ) const ( diff --git a/internal/storage/revision.go b/internal/storage/revision.go index be6f7078..14ef5a31 100644 --- a/internal/storage/revision.go +++ b/internal/storage/revision.go @@ -5,7 +5,7 @@ import ( "sort" "time" - "github.com/snyk/vervet/v7" + "github.com/snyk/vervet/v8" ) // ContentRevision is the exact contents and metadata of a service's version at scraping timestamp. diff --git a/internal/storage/revision_test.go b/internal/storage/revision_test.go index a36eb764..45248e06 100644 --- a/internal/storage/revision_test.go +++ b/internal/storage/revision_test.go @@ -6,8 +6,8 @@ import ( qt "github.com/frankban/quicktest" - "github.com/snyk/vervet/v7" - "github.com/snyk/vervet/v7/internal/storage" + "github.com/snyk/vervet/v8" + "github.com/snyk/vervet/v8/internal/storage" ) func TestServiceRevisions_ResolveLatestRevision(t *testing.T) { diff --git a/internal/storage/s3/client.go b/internal/storage/s3/client.go index 201fa502..d9cb13c4 100644 --- a/internal/storage/s3/client.go +++ b/internal/storage/s3/client.go @@ -22,8 +22,8 @@ import ( "github.com/rs/zerolog/log" "go.uber.org/multierr" - "github.com/snyk/vervet/v7" - "github.com/snyk/vervet/v7/internal/storage" + "github.com/snyk/vervet/v8" + "github.com/snyk/vervet/v8/internal/storage" ) // StaticKeyCredentials defines credential structure used in config.LoadDefaultConfig. diff --git a/internal/storage/s3/client_test.go b/internal/storage/s3/client_test.go index bb0d4877..5904def5 100644 --- a/internal/storage/s3/client_test.go +++ b/internal/storage/s3/client_test.go @@ -7,9 +7,9 @@ import ( qt "github.com/frankban/quicktest" - "github.com/snyk/vervet/v7/internal/storage" - "github.com/snyk/vervet/v7/internal/storage/s3" - s3testing "github.com/snyk/vervet/v7/internal/storage/s3/testing" + "github.com/snyk/vervet/v8/internal/storage" + "github.com/snyk/vervet/v8/internal/storage/s3" + s3testing "github.com/snyk/vervet/v8/internal/storage/s3/testing" ) func TestPutObject(t *testing.T) { diff --git a/internal/storage/s3/testing/testing.go b/internal/storage/s3/testing/testing.go index 68470f0b..25bb9cbe 100644 --- a/internal/storage/s3/testing/testing.go +++ b/internal/storage/s3/testing/testing.go @@ -6,7 +6,7 @@ import ( "github.com/elgohr/go-localstack" qt "github.com/frankban/quicktest" - "github.com/snyk/vervet/v7/internal/storage/s3" + "github.com/snyk/vervet/v8/internal/storage/s3" ) const ( diff --git a/internal/storage/storage.go b/internal/storage/storage.go index 692368a0..ac2a7cef 100644 --- a/internal/storage/storage.go +++ b/internal/storage/storage.go @@ -9,7 +9,7 @@ import ( "github.com/getkin/kin-openapi/openapi3" "github.com/rs/zerolog/log" - "github.com/snyk/vervet/v7" + "github.com/snyk/vervet/v8" ) // ReadOnlyStorage defines functionality needed to fetch spec versions. diff --git a/merge_test.go b/merge_test.go index 7fcb7ec4..77fbc14b 100644 --- a/merge_test.go +++ b/merge_test.go @@ -7,8 +7,8 @@ import ( "github.com/getkin/kin-openapi/openapi3" "github.com/google/go-cmp/cmp/cmpopts" - "github.com/snyk/vervet/v7" - "github.com/snyk/vervet/v7/testdata" + "github.com/snyk/vervet/v8" + "github.com/snyk/vervet/v8/testdata" ) var openapiCmp = qt.CmpEquals(cmpopts.IgnoreUnexported( diff --git a/ref_alias_resolver.go b/ref_alias_resolver.go index 3ac1fc3e..ff7b27b2 100644 --- a/ref_alias_resolver.go +++ b/ref_alias_resolver.go @@ -5,7 +5,7 @@ import ( "github.com/getkin/kin-openapi/openapi3" - "github.com/snyk/vervet/v7/internal/openapiwalker" + "github.com/snyk/vervet/v8/internal/openapiwalker" ) // refAliasResolver rewrites references in an OpenAPI document object to local diff --git a/ref_alias_resolver_test.go b/ref_alias_resolver_test.go index c4f63620..c34bb4fb 100644 --- a/ref_alias_resolver_test.go +++ b/ref_alias_resolver_test.go @@ -9,8 +9,8 @@ import ( qt "github.com/frankban/quicktest" - "github.com/snyk/vervet/v7" - "github.com/snyk/vervet/v7/testdata" + "github.com/snyk/vervet/v8" + "github.com/snyk/vervet/v8/testdata" ) func TestLocalize(t *testing.T) { diff --git a/ref_index_test.go b/ref_index_test.go index c9e6c0b2..2fb37a65 100644 --- a/ref_index_test.go +++ b/ref_index_test.go @@ -5,8 +5,8 @@ import ( qt "github.com/frankban/quicktest" - "github.com/snyk/vervet/v7" - "github.com/snyk/vervet/v7/testdata" + "github.com/snyk/vervet/v8" + "github.com/snyk/vervet/v8/testdata" ) func TestRefIndexSource(t *testing.T) { diff --git a/remove_elements_test.go b/remove_elements_test.go index f124440f..db6a8a4a 100644 --- a/remove_elements_test.go +++ b/remove_elements_test.go @@ -5,8 +5,8 @@ import ( qt "github.com/frankban/quicktest" - "github.com/snyk/vervet/v7" - "github.com/snyk/vervet/v7/testdata" + "github.com/snyk/vervet/v8" + "github.com/snyk/vervet/v8/testdata" ) func TestRemoveElementsExact(t *testing.T) { diff --git a/resource_test.go b/resource_test.go index 121347b0..2d2d9688 100644 --- a/resource_test.go +++ b/resource_test.go @@ -8,8 +8,8 @@ import ( qt "github.com/frankban/quicktest" - . "github.com/snyk/vervet/v7" - "github.com/snyk/vervet/v7/testdata" + . "github.com/snyk/vervet/v8" + "github.com/snyk/vervet/v8/testdata" ) func TestResource(t *testing.T) { diff --git a/spec_test.go b/spec_test.go index 4023d13e..3816e96d 100644 --- a/spec_test.go +++ b/spec_test.go @@ -6,8 +6,8 @@ import ( qt "github.com/frankban/quicktest" "github.com/getkin/kin-openapi/openapi3" - . "github.com/snyk/vervet/v7" - "github.com/snyk/vervet/v7/testdata" + . "github.com/snyk/vervet/v8" + "github.com/snyk/vervet/v8/testdata" ) func TestSpecs(t *testing.T) { diff --git a/util_test.go b/util_test.go index 827875b4..678cb669 100644 --- a/util_test.go +++ b/util_test.go @@ -6,8 +6,8 @@ import ( qt "github.com/frankban/quicktest" "github.com/ghodss/yaml" - "github.com/snyk/vervet/v7" - "github.com/snyk/vervet/v7/testdata" + "github.com/snyk/vervet/v8" + "github.com/snyk/vervet/v8/testdata" ) func TestToSpecYAML(t *testing.T) { diff --git a/version_test.go b/version_test.go index c9cb9fba..4a91b0f6 100644 --- a/version_test.go +++ b/version_test.go @@ -7,7 +7,7 @@ import ( qt "github.com/frankban/quicktest" - . "github.com/snyk/vervet/v7" + . "github.com/snyk/vervet/v8" ) func TestParseVersion(t *testing.T) { diff --git a/versionware/handler.go b/versionware/handler.go index f19c5a62..10d2799c 100644 --- a/versionware/handler.go +++ b/versionware/handler.go @@ -6,7 +6,7 @@ import ( "fmt" "net/http" - "github.com/snyk/vervet/v7" + "github.com/snyk/vervet/v8" ) const ( diff --git a/versionware/handler_test.go b/versionware/handler_test.go index b5c65c91..b6a44eea 100644 --- a/versionware/handler_test.go +++ b/versionware/handler_test.go @@ -9,8 +9,8 @@ import ( qt "github.com/frankban/quicktest" - "github.com/snyk/vervet/v7" - "github.com/snyk/vervet/v7/versionware" + "github.com/snyk/vervet/v8" + "github.com/snyk/vervet/v8/versionware" ) func ExampleHandler() { diff --git a/versionware/validator.go b/versionware/validator.go index a65f75ae..fe5da860 100644 --- a/versionware/validator.go +++ b/versionware/validator.go @@ -12,7 +12,7 @@ import ( "github.com/getkin/kin-openapi/openapi3filter" "github.com/getkin/kin-openapi/routers/gorillamux" - "github.com/snyk/vervet/v7" + "github.com/snyk/vervet/v8" ) // Validator provides versioned OpenAPI validation middleware for HTTP requests diff --git a/versionware/validator_test.go b/versionware/validator_test.go index 4d8ce4b3..753dd76b 100644 --- a/versionware/validator_test.go +++ b/versionware/validator_test.go @@ -15,7 +15,7 @@ import ( "github.com/getkin/kin-openapi/openapi3" "github.com/getkin/kin-openapi/openapi3filter" - "github.com/snyk/vervet/v7/versionware" + "github.com/snyk/vervet/v8/versionware" ) const (