func NewAzapiDefinitionsFromSwagger()

in resource/from_swagger.go [22:386]


func NewAzapiDefinitionsFromSwagger(apiPath swagger.ApiPath) []types.AzapiDefinition {
	methodMap := make(map[string]bool)
	for _, method := range apiPath.Methods {
		methodMap[method] = true
	}

	def := types.AzapiDefinition{
		Id:                apiPath.Path,
		AzureResourceType: apiPath.ResourceType,
		ApiVersion:        apiPath.ApiVersion,
		BodyFormat:        types.BodyFormatHcl,
		AdditionalFields:  make(map[string]types.Value),
	}

	label := defaultLabel(apiPath.ResourceType)
	caser := cases.Title(language.Und, cases.NoLower)
	res := make([]types.AzapiDefinition, 0)
	coveredMethodMap := make(map[string]bool)
	switch {
	case methodMap[http.MethodGet] && methodMap[http.MethodPut] && methodMap[http.MethodDelete]:
		coveredMethodMap[http.MethodGet] = true
		coveredMethodMap[http.MethodPut] = true
		coveredMethodMap[http.MethodDelete] = true
		def.LeadingComments = []string{
			fmt.Sprintf("OperationId: %s, %s, %s", apiPath.OperationIdMap[http.MethodPut], apiPath.OperationIdMap[http.MethodGet], apiPath.OperationIdMap[http.MethodDelete]),
			fmt.Sprintf("PUT GET DELETE %s", apiPath.Path),
		}
		def.Kind = types.KindResource
		def.ResourceName = "azapi_resource"
		def.AdditionalFields["parent_id"] = types.NewStringLiteralValue(utils.ParentIdOfResourceId(apiPath.Path))
		def.AdditionalFields["name"] = types.NewStringLiteralValue(utils.LastSegment(apiPath.Path))
		def.AdditionalFields["schema_validation_enabled"] = types.NewRawValue("false")
		def.Label = label
		examplePath := apiPath.ExampleMap[http.MethodPut]
		if requestBody, err := RequestBodyFromExample(examplePath); err == nil {
			def.Body = requestBody
			if requestBody != nil {
				if requestBodyMap, ok := def.Body.(map[string]interface{}); ok && requestBody != nil {
					if location := requestBodyMap["location"]; location != nil {
						def.AdditionalFields["location"] = types.NewStringLiteralValue(location.(string))
						delete(requestBodyMap, "location")
					}
					if name := requestBodyMap["name"]; name != nil {
						delete(requestBodyMap, "name")
					}
					delete(requestBodyMap, "id")
					def.Body = requestBodyMap
				}
			}
		} else {
			logrus.Warnf("failed to get request body from example, "+
				"this usually means that the `x-ms-examples` extension is not set correctly for %s in the swagger spec. %v", apiPath.Path, err)
		}
		if def.Label != "" {
			res = append(res, def)
		}
	case methodMap[http.MethodPut] && methodMap[http.MethodGet]:
		coveredMethodMap[http.MethodGet] = true
		coveredMethodMap[http.MethodPut] = true
		def.LeadingComments = []string{
			fmt.Sprintf("OperationId: %s", apiPath.OperationIdMap[http.MethodPut]),
			fmt.Sprintf("PUT %s", apiPath.Path),
		}
		def.Kind = types.KindResource
		def.ResourceName = "azapi_resource_action"
		def.AdditionalFields["resource_id"] = types.NewStringLiteralValue(apiPath.Path)
		def.AdditionalFields["method"] = types.NewStringLiteralValue(http.MethodPut)
		examplePath := apiPath.ExampleMap[http.MethodPut]
		if requestBody, err := RequestBodyFromExample(examplePath); err == nil {
			def.Body = requestBody
		} else {
			logrus.Warnf("failed to get request body from example, "+
				"this usually means that the `x-ms-examples` extension is not set correctly for %s in the swagger spec. %v", apiPath.Path, err)
		}
		def.Label = fmt.Sprintf("put_%s", label)
		res = append(res, def)

		def = types.AzapiDefinition{
			Id:                apiPath.Path,
			AzureResourceType: apiPath.ResourceType,
			ApiVersion:        apiPath.ApiVersion,
			BodyFormat:        types.BodyFormatHcl,
			AdditionalFields:  make(map[string]types.Value),
		}
		def.LeadingComments = []string{
			fmt.Sprintf("OperationId: %s", apiPath.OperationIdMap[http.MethodGet]),
			fmt.Sprintf("GET %s", apiPath.Path),
		}
		def.Kind = types.KindDataSource
		def.ResourceName = "azapi_resource"
		def.AdditionalFields["resource_id"] = types.NewStringLiteralValue(apiPath.Path)
		def.AdditionalFields["depends_on"] = types.NewRawValue(fmt.Sprintf("[ azapi_resource_action.put_%s ]", label))
		def.Label = label
		res = append(res, def)
	case methodMap[http.MethodPut]:
		coveredMethodMap[http.MethodPut] = true
		def.LeadingComments = []string{
			fmt.Sprintf("OperationId: %s", apiPath.OperationIdMap[http.MethodPut]),
			fmt.Sprintf("PUT %s", apiPath.Path),
		}
		def.Kind = types.KindResource
		def.ResourceName = "azapi_resource_action"
		def.AdditionalFields["resource_id"] = types.NewStringLiteralValue(ResourceIdFromActionPath(apiPath.Path))
		def.AdditionalFields["method"] = types.NewStringLiteralValue(http.MethodPut)
		action := utils.ActionName(apiPath.Path)
		def.AdditionalFields["action"] = types.NewStringLiteralValue(action)
		if action != "" {
			def.Label = action
		} else {
			def.Label = fmt.Sprintf("put_%s", label)
		}
		examplePath := apiPath.ExampleMap[http.MethodPut]
		if requestBody, err := RequestBodyFromExample(examplePath); err == nil {
			def.Body = requestBody
		} else {
			logrus.Warnf("failed to get request body from example, "+
				"this usually means that the `x-ms-examples` extension is not set correctly for %s in the swagger spec. %v", apiPath.Path, err)
		}
		if def.Label != "" {
			res = append(res, def)
		}
	case len(methodMap) == 1 && methodMap[http.MethodGet]:
		coveredMethodMap[http.MethodGet] = true
		def.LeadingComments = []string{
			fmt.Sprintf("OperationId: %s", apiPath.OperationIdMap[http.MethodGet]),
			fmt.Sprintf("%s %s", http.MethodGet, apiPath.Path),
		}
		def.Kind = types.KindDataSource
		switch apiPath.ApiType {
		case swagger.ApiTypeList:
			def.ResourceName = "azapi_resource_list"
			parentId := utils.ScopeOfListAction(apiPath.Path)
			def.AdditionalFields["parent_id"] = types.NewStringLiteralValue(parentId)
			resourceName := def.AzureResourceType[strings.LastIndex(def.AzureResourceType, "/")+1:]
			scope := caser.String(defaultLabel(utils.ResourceTypeOfResourceId(parentId)))
			def.Label = fmt.Sprintf("list%sBy%s", caser.String(resourceName), scope)
		case swagger.ApiTypeResource:
			def.ResourceName = "azapi_resource"
			def.AdditionalFields["parent_id"] = types.NewStringLiteralValue(utils.ParentIdOfResourceId(apiPath.Path))
			def.AdditionalFields["name"] = types.NewStringLiteralValue(utils.LastSegment(apiPath.Path))
			def.Label = label
		case swagger.ApiTypeResourceAction, swagger.ApiTypeProviderAction:
			def.ResourceName = "azapi_resource_action"
			def.AdditionalFields["method"] = types.NewStringLiteralValue(http.MethodGet)
			def.AdditionalFields["resource_id"] = types.NewStringLiteralValue(ResourceIdFromActionPath(apiPath.Path))
			action := utils.ActionName(apiPath.Path)
			def.AdditionalFields["action"] = types.NewStringLiteralValue(action)
			def.Label = action
			if def.Label == "" {
				def.Label = utils.LastSegment(apiPath.Path)
			}
		}
		if def.Label != "" {
			res = append(res, def)
		}
	case len(methodMap) == 1 && methodMap[http.MethodPost]:
		coveredMethodMap[http.MethodPost] = true
		def.LeadingComments = []string{
			fmt.Sprintf("OperationId: %s", apiPath.OperationIdMap[http.MethodPost]),
			fmt.Sprintf("%s %s", http.MethodPost, apiPath.Path),
		}
		def.ResourceName = "azapi_resource_action"
		def.AdditionalFields["method"] = types.NewStringLiteralValue(http.MethodPost)
		def.AdditionalFields["resource_id"] = types.NewStringLiteralValue(ResourceIdFromActionPath(apiPath.Path))
		action := utils.ActionName(apiPath.Path)
		def.AdditionalFields["action"] = types.NewStringLiteralValue(action)
		def.Label = action
		if def.Label == "" {
			def.Label = utils.LastSegment(apiPath.Path)
		}
		// defaults to resource, but if the request body is nil, it's a data source
		// TODO: check the swagger spec to see if it's a data source
		def.Kind = types.KindResource
		examplePath := apiPath.ExampleMap[http.MethodPost]
		if requestBody, err := RequestBodyFromExample(examplePath); err == nil {
			def.Body = requestBody
		} else {
			logrus.Warnf("failed to get request body from example, "+
				"this usually means that the `x-ms-examples` extension is not set correctly for %s in the swagger spec. %v", apiPath.Path, err)
		}
		if def.Label != "" {
			res = append(res, def)
		}
	case methodMap[http.MethodGet] && methodMap[http.MethodDelete]:
		coveredMethodMap[http.MethodGet] = true
		coveredMethodMap[http.MethodDelete] = true
		def.LeadingComments = []string{
			fmt.Sprintf("OperationId: %s", apiPath.OperationIdMap[http.MethodGet]),
			fmt.Sprintf("GET %s", apiPath.Path),
		}
		def.Kind = types.KindResource
		def.ResourceName = "azapi_resource_action"
		def.AdditionalFields["resource_id"] = types.NewStringLiteralValue(apiPath.Path)
		def.AdditionalFields["method"] = types.NewStringLiteralValue(http.MethodGet)
		def.Label = fmt.Sprintf("get_%s", label)
		res = append(res, def)

		def = types.AzapiDefinition{
			Id:                apiPath.Path,
			AzureResourceType: apiPath.ResourceType,
			ApiVersion:        apiPath.ApiVersion,
			BodyFormat:        types.BodyFormatHcl,
			AdditionalFields:  make(map[string]types.Value),
		}
		def.LeadingComments = []string{
			fmt.Sprintf("OperationId: %s", apiPath.OperationIdMap[http.MethodDelete]),
			fmt.Sprintf("DELETE %s", apiPath.Path),
		}
		def.Kind = types.KindResource
		def.ResourceName = "azapi_resource_action"
		def.AdditionalFields["resource_id"] = types.NewStringLiteralValue(apiPath.Path)
		def.AdditionalFields["method"] = types.NewStringLiteralValue(http.MethodDelete)
		def.AdditionalFields["depends_on"] = types.NewRawValue(fmt.Sprintf("[ azapi_resource_action.get_%s ]", label))
		def.Label = fmt.Sprintf("delete_%s", label)
		res = append(res, def)
	case methodMap[http.MethodGet] && methodMap[http.MethodPatch]:
		coveredMethodMap[http.MethodGet] = true
		coveredMethodMap[http.MethodPatch] = true

		def.LeadingComments = []string{
			fmt.Sprintf("OperationId: %s", apiPath.OperationIdMap[http.MethodPatch]),
			fmt.Sprintf("PATCH %s", apiPath.Path),
		}
		def.Kind = types.KindResource
		def.ResourceName = "azapi_resource_action"
		def.AdditionalFields["resource_id"] = types.NewStringLiteralValue(apiPath.Path)
		def.AdditionalFields["method"] = types.NewStringLiteralValue(http.MethodPatch)
		examplePath := apiPath.ExampleMap[http.MethodPatch]
		if requestBody, err := RequestBodyFromExample(examplePath); err == nil {
			def.Body = requestBody
			if requestBody != nil {
				if requestBodyMap, ok := def.Body.(map[string]interface{}); ok && requestBody != nil {
					if location := requestBodyMap["location"]; location != nil {
						delete(requestBodyMap, "location")
					}
					if name := requestBodyMap["name"]; name != nil {
						delete(requestBodyMap, "name")
					}
					delete(requestBodyMap, "id")
					def.Body = requestBodyMap
				}
			}
		} else {
			logrus.Warnf("failed to get request body from example, "+
				"this usually means that the `x-ms-examples` extension is not set correctly for %s in the swagger spec. %v", apiPath.Path, err)
		}
		def.Label = fmt.Sprintf("patch_%s", label)
		res = append(res, def)

		def = types.AzapiDefinition{
			Id:                apiPath.Path,
			AzureResourceType: apiPath.ResourceType,
			ApiVersion:        apiPath.ApiVersion,
			BodyFormat:        types.BodyFormatHcl,
			AdditionalFields:  make(map[string]types.Value),
		}
		def.LeadingComments = []string{
			fmt.Sprintf("OperationId: %s", apiPath.OperationIdMap[http.MethodGet]),
			fmt.Sprintf("GET %s", apiPath.Path),
		}
		def.Kind = types.KindDataSource
		def.ResourceName = "azapi_resource"
		def.AdditionalFields["resource_id"] = types.NewStringLiteralValue(apiPath.Path)
		def.AdditionalFields["depends_on"] = types.NewRawValue(fmt.Sprintf("[ azapi_resource_action.patch_%s ]", label))
		def.Label = label
		res = append(res, def)
	}

	if methodMap[http.MethodPatch] && !coveredMethodMap[http.MethodPatch] {
		coveredMethodMap[http.MethodPatch] = true
		def := types.AzapiDefinition{
			AzureResourceType: apiPath.ResourceType,
			ApiVersion:        apiPath.ApiVersion,
			BodyFormat:        types.BodyFormatHcl,
			AdditionalFields:  make(map[string]types.Value),
		}
		def.LeadingComments = []string{
			fmt.Sprintf("OperationId: %s", apiPath.OperationIdMap[http.MethodPatch]),
			fmt.Sprintf("PATCH %s", apiPath.Path),
		}
		def.Kind = types.KindResource
		def.ResourceName = "azapi_resource_action"
		def.AdditionalFields["method"] = types.NewStringLiteralValue(http.MethodPatch)
		def.AdditionalFields["resource_id"] = types.NewStringLiteralValue(ResourceIdFromActionPath(apiPath.Path))
		action := utils.ActionName(apiPath.Path)
		def.AdditionalFields["action"] = types.NewStringLiteralValue(action)
		if action != "" {
			def.Label = action
		} else {
			def.Label = fmt.Sprintf("patch_%s", label)
		}
		examplePath := apiPath.ExampleMap[http.MethodPatch]
		if requestBody, err := RequestBodyFromExample(examplePath); err == nil {
			def.Body = requestBody
			if requestBody != nil {
				if requestBodyMap, ok := def.Body.(map[string]interface{}); ok && requestBody != nil {
					if location := requestBodyMap["location"]; location != nil {
						delete(requestBodyMap, "location")
					}
					if name := requestBodyMap["name"]; name != nil {
						delete(requestBodyMap, "name")
					}
					delete(requestBodyMap, "id")
					def.Body = requestBodyMap
				}
			}
		} else {
			logrus.Warnf("failed to get request body from example, "+
				"this usually means that the `x-ms-examples` extension is not set correctly for %s in the swagger spec. %v", apiPath.Path, err)
		}
		res = append(res, def)
	}

	if methodMap[http.MethodHead] {
		coveredMethodMap[http.MethodHead] = true
		def := types.AzapiDefinition{
			AzureResourceType: apiPath.ResourceType,
			ApiVersion:        apiPath.ApiVersion,
			BodyFormat:        types.BodyFormatHcl,
			AdditionalFields:  make(map[string]types.Value),
		}
		def.LeadingComments = []string{
			fmt.Sprintf("OperationId: %s", apiPath.OperationIdMap[http.MethodHead]),
			fmt.Sprintf("HEAD %s", apiPath.Path),
		}
		def.Kind = types.KindResource
		def.ResourceName = "azapi_resource_action"
		def.AdditionalFields["method"] = types.NewStringLiteralValue(http.MethodHead)
		def.AdditionalFields["resource_id"] = types.NewStringLiteralValue(ResourceIdFromActionPath(apiPath.Path))
		action := utils.ActionName(apiPath.Path)
		def.AdditionalFields["action"] = types.NewStringLiteralValue(action)
		if action != "" {
			def.Label = action
		} else {
			def.Label = fmt.Sprintf("head_%s", label)
		}
		res = append(res, def)
	}

	if methodMap[http.MethodDelete] && !coveredMethodMap[http.MethodDelete] {
		coveredMethodMap[http.MethodDelete] = true
		def.LeadingComments = []string{
			fmt.Sprintf("OperationId: %s", apiPath.OperationIdMap[http.MethodDelete]),
			fmt.Sprintf("DELETE %s", apiPath.Path),
		}
		def.Kind = types.KindResource
		def.ResourceName = "azapi_resource_action"
		def.AdditionalFields["resource_id"] = types.NewStringLiteralValue(apiPath.Path)
		def.AdditionalFields["method"] = types.NewStringLiteralValue(http.MethodDelete)
		def.Label = fmt.Sprintf("delete_%s", label)
		res = append(res, def)
	}

	notCoveredMethods := make([]string, 0)
	for method := range methodMap {
		if !coveredMethodMap[method] {
			notCoveredMethods = append(notCoveredMethods, method)
		}
	}
	if len(notCoveredMethods) != 0 {
		// TODO: GET and POST on a collection URL are not supported
		logrus.Errorf("there are methods not covered: %v for API path %s", notCoveredMethods, apiPath.Path)
	}
	return res
}