func Load()

in swagger/swagger.go [18:141]


func Load(swaggerPath string) ([]ApiPath, error) {
	swaggerSpec, err := loads.JSONSpec(swaggerPath)
	if err != nil {
		return nil, err
	}

	paths := swaggerSpec.Spec().Paths
	if paths == nil {
		return nil, fmt.Errorf("paths is nil, swagger path: %v", swaggerPath)
	}

	apiVersion := swaggerSpec.Spec().Info.Version

	apiPaths := make([]ApiPath, 0)
	for pathKey, pathItem := range paths.Paths {
		apiPath := ApiPath{
			Path:         pathKey,
			ApiVersion:   apiVersion,
			ResourceType: utils.ResourceTypeOfResourceId(pathKey),
			ApiType:      ApiTypeUnknown,
		}

		operationMap := make(map[string]spec.Operation)
		if pathItem.Get != nil {
			operationMap[http.MethodGet] = *pathItem.Get
		}
		if pathItem.Put != nil {
			operationMap[http.MethodPut] = *pathItem.Put
		}
		if pathItem.Post != nil {
			operationMap[http.MethodPost] = *pathItem.Post
		}
		if pathItem.Delete != nil {
			operationMap[http.MethodDelete] = *pathItem.Delete
		}
		if pathItem.Patch != nil {
			operationMap[http.MethodPatch] = *pathItem.Patch
		}
		if pathItem.Head != nil {
			operationMap[http.MethodHead] = *pathItem.Head
		}

		methods := make([]string, 0)
		exampleMap := make(map[string]string)
		operationIdMap := make(map[string]string)
		for method, operation := range operationMap {
			methods = append(methods, method)
			// the example is in the Extensions["x-ms-examples"], here's an example:
			// "x-ms-examples": {
			//   "Get lists of an automation account": {
			//     "$ref": "./examples/listAutomationAccountKeys.json"
			//   }
			// },
			exampleList := make([]string, 0)
			if operation.Extensions != nil && operation.Extensions["x-ms-examples"] != nil {
				if examples, ok := operation.Extensions["x-ms-examples"].(map[string]interface{}); ok && examples != nil {
					for _, exampleItem := range examples {
						if exampleItemMap, ok := exampleItem.(map[string]interface{}); ok && exampleItemMap != nil {
							exampleRef := exampleItemMap["$ref"]
							if exampleRef == nil {
								continue
							}
							exampleList = append(exampleList, path.Clean(path.Join(filepath.ToSlash(swaggerPath), "..", exampleRef.(string))))
						}
					}
				}
			}
			sort.Strings(exampleList)
			if len(exampleList) > 0 {
				exampleMap[method] = exampleList[0]
			}
			operationIdMap[method] = operation.ID
		}

		sort.Strings(methods)
		apiPath.Methods = methods
		apiPath.ExampleMap = exampleMap
		apiPath.OperationIdMap = operationIdMap
		apiPaths = append(apiPaths, apiPath)
	}

	// check the operation whether it's a list operation
	// for example:
	// /subscriptions/{subscriptionId}/providers/Microsoft.Automation/automationAccounts
	// /.../providers/Microsoft.Automation/automationAccounts/{automationAccountName}/modules
	resourceTypes := make(map[string]bool)
	// add a special resource type "operations"
	resourceTypes["operations"] = true
	for _, apiPath := range apiPaths {
		if lastSegment := utils.LastSegment(apiPath.ResourceType); lastSegment != "" {
			resourceTypes[lastSegment] = true
		}
	}
	for i, apiPath := range apiPaths {
		if len(apiPath.Methods) != 1 || apiPath.Methods[0] != http.MethodGet {
			continue
		}
		lastSegment := utils.LastSegment(apiPath.Path)
		if lastSegment != "" && resourceTypes[lastSegment] {
			apiPaths[i].ResourceType += "/" + lastSegment
			apiPaths[i].ApiType = ApiTypeList
		}
	}

	// decide the api type
	for i, apiPath := range apiPaths {
		if apiPath.ApiType != ApiTypeUnknown {
			continue
		}
		switch {
		case !utils.IsAction(apiPath.Path):
			apiPaths[i].ApiType = ApiTypeResource
		case strings.Contains(apiPath.ResourceType, "/"):
			apiPaths[i].ApiType = ApiTypeResourceAction
		default:
			apiPaths[i].ApiType = ApiTypeProviderAction
		}
	}

	slices.SortFunc(apiPaths, func(i, j ApiPath) int {
		return strings.Compare(i.Path, j.Path)
	})
	return apiPaths, nil
}