in internal/services/resource.go [22:128]
func schemaValidate(config *AzapiResourceModel) error {
if config == nil {
return nil
}
azureResourceType, apiVersion, err := utils.GetAzureResourceTypeApiVersion(config.Type.ValueString())
if err != nil {
return fmt.Errorf(`the argument "type" is invalid: %s`, err.Error())
}
resourceDef, _ := azure.GetResourceDefinition(azureResourceType, apiVersion)
log.Printf("[INFO] prepare validation for resource type: %s, api-version: %s", azureResourceType, apiVersion)
versions := azure.GetApiVersions(azureResourceType)
if len(versions) == 0 {
return schemaValidationError(fmt.Sprintf("the argument \"type\" is invalid.\n resource type %s can't be found.\n", azureResourceType))
}
isVersionValid := false
for _, version := range versions {
if version == apiVersion {
isVersionValid = true
break
}
}
if !isVersionValid {
return schemaValidationError(fmt.Sprintf("the argument \"type\"'s api-version is invalid.\n The supported versions are [%s].\n", strings.Join(versions, ", ")))
}
if resourceDef == nil {
return nil
}
var bodyToValidate attr.Value
if !config.Body.IsNull() && !config.Body.IsUnknown() && !config.Body.IsNull() && !config.Body.IsUnderlyingValueUnknown() {
if v, ok := config.Body.UnderlyingValue().(types.Object); ok {
attributes := v.Attributes()
attributeTypes := v.AttributeTypes(context.Background())
attributes["name"] = config.Name
attributeTypes["name"] = types.StringType
if !config.Location.IsNull() {
attributes["location"] = config.Location
attributeTypes["location"] = types.StringType
}
if !config.Tags.IsNull() {
attributes["tags"] = config.Tags
attributeTypes["tags"] = types.MapType{ElemType: types.StringType}
}
if !config.Identity.IsNull() {
identityAttributeTypes := map[string]attr.Type{
"type": types.StringType,
}
identityModel := identity.FromList(config.Identity)
if len(identityModel.IdentityIDs.Elements()) != 0 {
identityAttributeTypes["userAssignedIdentities"] = types.MapType{ElemType: types.DynamicType}
elements := make(map[string]attr.Value)
identityIds := identityModel.IdentityIDs.Elements()
for _, identityId := range identityIds {
elements[identityId.(types.String).ValueString()] = types.DynamicNull()
}
attributes["identity"] = types.ObjectValueMust(identityAttributeTypes, map[string]attr.Value{
"type": identityModel.Type,
"userAssignedIdentities": types.MapValueMust(types.DynamicType, elements),
})
} else {
attributes["identity"] = types.ObjectValueMust(identityAttributeTypes, map[string]attr.Value{
"type": identityModel.Type,
})
}
attributeTypes["identity"] = types.ObjectType{AttrTypes: identityAttributeTypes}
}
bodyToValidate = types.ObjectValueMust(attributeTypes, attributes)
}
} else {
bodyToValidate = config.Body
}
bodyToValidate, err = dynamic.MergeDynamic(types.DynamicValue(bodyToValidate), config.SensitiveBody)
if err != nil {
return fmt.Errorf("failed to merge write-only body: %s", err)
}
validateErrors := (*resourceDef).Validate(bodyToValidate, "")
errors := make([]error, 0)
// skip error that location is not in the body, because user might use the default location feature
// same for tags
for _, err := range validateErrors {
if strings.Contains(err.Error(), "`location` is required") || strings.Contains(err.Error(), "`tags` is required") {
continue
}
errors = append(errors, err)
}
if len(errors) != 0 {
errorMsg := "the argument \"body\" is invalid:\n"
for _, err := range errors {
errorMsg += fmt.Sprintf("%s\n", err.Error())
}
return schemaValidationError(errorMsg)
}
return nil
}