coverage/from_local_spec.go (121 lines of code) (raw):

package coverage import ( "fmt" "os" "path/filepath" "strings" "github.com/azure/armstrong/utils" openapispec "github.com/go-openapi/spec" "github.com/sirupsen/logrus" ) func GetModelInfoFromLocalDir(resourceId, swaggerPath string, method string) (*SwaggerModel, error) { swaggerPath, err := filepath.Abs(swaggerPath) if err != nil { return nil, err } file, err := os.Stat(swaggerPath) if err != nil { return nil, err } if !file.IsDir() { return GetModelInfoFromLocalSpecFile(resourceId, swaggerPath, method) } files, err := utils.ListFiles(swaggerPath, ".json", 1) if err != nil { return nil, err } for _, filename := range files { model, err := GetModelInfoFromLocalSpecFile(resourceId, filename, method) if err != nil { logrus.Warnf("failed to get model info from local spec file %v: %+v", filename, err) } if model != nil { return model, nil } } return nil, nil } func GetModelInfoFromLocalSpecFile(resourceId, swaggerPath string, method string) (*SwaggerModel, error) { doc, err := loadSwagger(swaggerPath) if err != nil { return nil, err } paths := doc.Spec().Paths if paths == nil { return nil, fmt.Errorf("paths is nil, swagger path: %v", swaggerPath) } for pathKey, pathItem := range paths.Paths { if !IsPathKeyMatchWithResourceId(pathKey, resourceId) { continue } var operation *openapispec.Operation switch strings.ToUpper(method) { case "GET": operation = pathItem.Get case "PUT": operation = pathItem.Put case "POST": operation = pathItem.Post case "DELETE": operation = pathItem.Delete case "OPTIONS": operation = pathItem.Options case "HEAD": operation = pathItem.Head case "PATCH": operation = pathItem.Patch default: logrus.Warnf("unsupported method %v", method) } if operation == nil { // should not happen logrus.Warnf("no PUT operation found for path %v", pathKey) continue } var modelName string for _, param := range operation.Parameters { paramRef := param.Ref if paramRef.String() != "" { refParam, err := openapispec.ResolveParameterWithBase(nil, param.Ref, &openapispec.ExpandOptions{RelativeBase: swaggerPath}) if err != nil { return nil, fmt.Errorf("resolve param ref %q: %+v", param.Ref.String(), err) } // Update the param param = *refParam } if param.In == "body" { if paramRef.String() != "" { modelName, swaggerPath = SchemaNamePathFromRef(swaggerPath, paramRef) } if param.Schema.Ref.String() != "" { modelName, swaggerPath = SchemaNamePathFromRef(swaggerPath, param.Schema.Ref) } break } } return &SwaggerModel{ ApiPath: pathKey, ModelName: modelName, SwaggerPath: swaggerPath, OperationID: operation.ID, }, nil } return nil, nil } func IsPathKeyMatchWithResourceId(pathKey, resourceId string) bool { pathParts := strings.Split(strings.Trim(pathKey, "/"), "/") resourceIdParts := strings.Split(strings.Trim(resourceId, "/"), "/") i := len(pathParts) - 1 j := len(resourceIdParts) - 1 for i >= 0 && j >= 0 { if i == 0 && (strings.EqualFold(pathParts[i], "{resourceid}") || strings.EqualFold(pathParts[i], "{scope}") || strings.EqualFold(pathParts[i], "{resourceUri}")) { return true } if strings.EqualFold(pathParts[i], resourceIdParts[j]) || strings.HasPrefix(pathParts[i], "{") && strings.HasSuffix(pathParts[i], "}") { i-- j-- } else { break } } return i < 0 && j < 0 }