// Copyright 2020 Google LLC. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package linter import ( "fmt" "os" rules "github.com/google/gnostic/metrics/rules" openapi_v3 "github.com/google/gnostic/openapiv3" ) // processParametersV2 loops over the parameters of component and creates a // Field struct slice which will be used for the linter. func processParametersV3(components *openapi_v3.Components, path []string) []rules.Field { parameters := make([]rules.Field, 0) if components.Parameters != nil { for _, pair := range components.Parameters.AdditionalProperties { switch t := pair.Value.Oneof.(type) { case *openapi_v3.ParameterOrReference_Parameter: parameters = append(parameters, rules.Field{Name: t.Parameter.Name, Path: append(path, pair.Name, "name")}) } } } return parameters } // processParametersV2 loops over the parameters of an operation and creates a // Field struct slice which will be used for the linter. func processOperationV3(operation *openapi_v3.Operation, path []string) []rules.Field { parameters := make([]rules.Field, 0) for _, item := range operation.Parameters { fmt.Fprintf(os.Stderr, "%+v\n", item) switch t := item.Oneof.(type) { case *openapi_v3.ParameterOrReference_Parameter: parameters = append(parameters, rules.Field{Name: t.Parameter.Name, Path: path}) } } return parameters } // gatherParametersV2 takes a Document struct as a parameter and calls the // processParamater function on components and each HTTP request in order // to gather the parameters. func gatherParameters(document *openapi_v3.Document) []rules.Field { p := make([]rules.Field, 0) if document.Components != nil { path := []string{"components", "parameters"} p = append(p, processParametersV3(document.Components, path)...) } if document.Paths != nil { for _, pair := range document.Paths.Path { fmt.Fprintf(os.Stderr, "%+v\n", pair) v := pair.Value path := []string{"paths", pair.Name} if v.Get != nil { p = append(p, processOperationV3(v.Get, append(path, "get", "parameters", "name"))...) } if v.Post != nil { p = append(p, processOperationV3(v.Post, append(path, "post", "parameters", "name"))...) } if v.Put != nil { p = append(p, processOperationV3(v.Put, append(path, "put", "parameters", "name"))...) } if v.Patch != nil { p = append(p, processOperationV3(v.Patch, append(path, "patch", "parameters", "name"))...) } if v.Delete != nil { p = append(p, processOperationV3(v.Delete, append(path, "delete", "parameters", "name"))...) } } } return p } //AIPLintV3 accepts an OpenAPI v2 document and will call the individual AIP rules //on the document. func AIPLintV3(document *openapi_v3.Document) (*Linter, int) { fields := gatherParameters(document) messages := make([]rules.MessageType, 0) for _, field := range fields { messages = append(messages, rules.AIP122Driver(field)...) messages = append(messages, rules.AIP140Driver(field)...) } m := fillProtoStructure(messages) linterResult := &Linter{ Messages: m, } return linterResult, len(messages) }