func createResource()

in tpgtools/resource.go [441:724]


func createResource(schema *openapi.Schema, info *openapi.Info, typeFetcher *TypeFetcher, overrides Overrides, product *ProductMetadata, version Version, location string) (*Resource, error) {
	resourceTitle := strings.Split(info.Title, "/")[1]

	res := Resource{
		title:                SnakeCaseTerraformResourceName(jsonToSnakeCase(resourceTitle).snakecase()),
		dclStructName:        TitleCaseResourceName(schema.Title),
		dclTitle:             TitleCaseResourceName(resourceTitle),
		productMetadata:      product,
		versionMetadata:      version,
		Description:          info.Description,
		location:             location,
		InsertTimeoutMinutes: 20,
		UpdateTimeoutMinutes: 20,
		DeleteTimeoutMinutes: 20,
	}

	// Since the resource's "info" extension field can't be accessed, the relevant
	// extensions have been copied into the schema objects.
	res.fillLinksFromExtensionsMap(schema.Extension)

	// Resource Override: Custom Timeout
	ctd := CustomTimeoutDetails{}
	ctdOk, err := overrides.ResourceOverrideWithDetails(CustomTimeout, &ctd, location)
	if err != nil {
		return nil, fmt.Errorf("failed to decode custom timeout details: %v", err)
	}
	if ctdOk {
		res.InsertTimeoutMinutes = ctd.TimeoutMinutes
		res.UpdateTimeoutMinutes = ctd.TimeoutMinutes
		res.DeleteTimeoutMinutes = ctd.TimeoutMinutes
	}

	if overrides.ResourceOverride(SkipInProvider, location) {
		res.SkipInProvider = true
	}

	crname := CustomResourceNameDetails{}
	crnameOk, err := overrides.ResourceOverrideWithDetails(CustomResourceName, &crname, location)
	if err != nil {
		return nil, fmt.Errorf("failed to decode custom resource name details: %v", err)
	}

	if crnameOk {
		res.title = SnakeCaseTerraformResourceName(crname.Title)
	}

	id, customID, err := findResourceID(schema, overrides, location)
	if err != nil {
		return nil, err
	}
	res.ID = id
	res.UseTerraformID = customID

	// Resource Override: Custom Import Function
	cifd := CustomImportFunctionDetails{}
	cifdOk, err := overrides.ResourceOverrideWithDetails(CustomImport, &cifd, location)
	if err != nil {
		return nil, fmt.Errorf("failed to decode custom import function details: %v", err)
	}
	if cifdOk {
		res.CustomImportFunction = &cifd.Function
	}

	// Resource Override: Append to Base Path
	atbpd := AppendToBasePathDetails{}
	atbpOk, err := overrides.ResourceOverrideWithDetails(AppendToBasePath, &atbpd, location)
	if err != nil {
		return nil, fmt.Errorf("failed to decode append to base path details: %v", err)
	}
	if atbpOk {
		res.AppendToBasePath = atbpd.String
	}

	// Resource Override: Replace in Base Path
	ribpd := ReplaceInBasePathDetails{}
	ribpOk, err := overrides.ResourceOverrideWithDetails(ReplaceInBasePath, &ribpd, location)
	if err != nil {
		return nil, fmt.Errorf("failed to decode replace in base path details: %v", err)
	}
	if ribpOk {
		res.ReplaceInBasePath.Present = true
		res.ReplaceInBasePath.Old = ribpd.Old
		res.ReplaceInBasePath.New = ribpd.New
	}

	// Resource Override: Mutex
	md := MutexDetails{}
	mdOk, err := overrides.ResourceOverrideWithDetails(Mutex, &md, location)
	if err != nil {
		return nil, fmt.Errorf("failed to decode mutex details: %v", err)
	}
	if mdOk {
		res.Mutex = md.Mutex
	}

	props, err := createPropertiesFromSchema(schema, typeFetcher, overrides, &res, nil, location)
	if err != nil {
		return nil, err
	}

	res.Properties = props

	onlyLongFormFormat := shouldAllowForwardSlashInFormat(res.ID, res.Properties)
	// Resource Override: Import formats
	ifd := ImportFormatDetails{}
	ifdOk, err := overrides.ResourceOverrideWithDetails(ImportFormat, &ifd, location)
	if err != nil {
		return nil, fmt.Errorf("failed to decode import format details: %v", err)
	}
	if ifdOk {
		res.ImportFormats = ifd.Formats
	} else {
		res.ImportFormats = defaultImportFormats(res.ID, onlyLongFormFormat)
	}

	_, res.HasProject = schema.Properties["project"]

	// Resource Override: Virtual field
	for _, vfd := range overrides.ResourceOverridesWithDetails(VirtualField, location) {
		vf := VirtualFieldDetails{}
		if err := convert(vfd, &vf); err != nil {
			return nil, fmt.Errorf("error converting type: %v", err)
		}

		res.Properties = append(res.Properties, readVirtualField(vf))
	}

	// Resource-level pre and post action functions
	preCreate := PreCreateFunctionDetails{}
	preCreOk, err := overrides.ResourceOverrideWithDetails(PreCreate, &preCreate, location)
	if err != nil {
		return nil, fmt.Errorf("failed to decode pre create function details: %v", err)
	}
	if preCreOk {
		res.PreCreateFunction = &preCreate.Function
	}

	postCreate := PostCreateFunctionDetails{}
	postCreOk, err := overrides.ResourceOverrideWithDetails(PostCreate, &postCreate, location)
	if err != nil {
		return nil, fmt.Errorf("failed to decode post create function details: %v", err)
	}
	if postCreOk {
		res.PostCreateFunction = &postCreate.Function
	}

	pd := PreDeleteFunctionDetails{}
	pdOk, err := overrides.ResourceOverrideWithDetails(PreDelete, &pd, location)
	if err != nil {
		return nil, fmt.Errorf("failed to decode pre delete function details: %v", err)
	}
	if pdOk {
		res.PreDeleteFunction = &pd.Function
	}

	// Resource Override: Customize Diff
	cdiff := CustomizeDiffDetails{}
	cdOk, err := overrides.ResourceOverrideWithDetails(CustomizeDiff, &cdiff, location)
	if err != nil {
		return nil, fmt.Errorf("failed to decode customize diff details: %v", err)
	}

	if cdOk {
		res.CustomizeDiff = cdiff.Functions
	}

	if res.HasLabels() {
		res.CustomizeDiff = append(res.CustomizeDiff, "tpgresource.SetLabelsDiff")
	}

	if res.HasAnnotations() {
		res.CustomizeDiff = append(res.CustomizeDiff, "tpgresource.SetAnnotationsDiff")
	}

	// ListFields
	if parameters, ok := typeFetcher.doc.Paths["list"]; ok {
		for _, param := range parameters.Parameters {
			if param.Name != "" {
				res.ListFields = append(res.ListFields, param.Name)
			}
		}
	}

	// Determine if a resource has a create method.
	res.HasCreate, _ = schema.Extension["x-dcl-has-create"].(bool)

	// Determine if a resource can use a generated sweeper or not
	// We only supply a certain set of parent values to sweepers, so only generate
	// one if it will actually work- resources with resource parents are not
	// sweepable, in particular, such as nested resources or fine-grained
	// resources. Additional special cases can be handled with overrides.
	res.HasSweeper = true
	validSweeperParameters := []string{"project", "region", "location", "zone", "billingAccount"}
	if deleteAllInfo, ok := typeFetcher.doc.Paths["deleteAll"]; ok {
		for _, p := range deleteAllInfo.Parameters {
			// if any field isn't a standard sweeper parameter, don't make a sweeper
			if !stringInSlice(p.Name, validSweeperParameters) {
				res.HasSweeper = false
			}
		}
	} else {
		// if deleteAll wasn't found, the DCL hasn't published a sweeper
		res.HasSweeper = false
	}

	if overrides.ResourceOverride(NoSweeper, location) {
		if res.HasSweeper == false {
			return nil, fmt.Errorf("superfluous NO_SWEEPER specified for %q", res.TerraformName())
		}

		res.HasSweeper = false
	}

	stateHint, ok := schema.Extension["x-dcl-uses-state-hint"].(bool)
	if ok {
		res.StateHint = stateHint
	}

	// Resource Override: CustomCreateDirectiveFunction
	createDirectiveFunc := CustomCreateDirectiveDetails{}
	createDirectiveFuncOk, err := overrides.ResourceOverrideWithDetails(CustomCreateDirective, &createDirectiveFunc, location)
	if err != nil {
		return nil, fmt.Errorf("failed to decode custom create directive function details: %v", err)
	}
	if createDirectiveFuncOk {
		res.CustomCreateDirectiveFunction = &createDirectiveFunc.Function
	}

	// Resource Override: SkipDeleteFunction
	skipDeleteFunc := SkipDeleteFunctionDetails{}
	skipDeleteFuncOk, err := overrides.ResourceOverrideWithDetails(SkipDeleteFunction, &skipDeleteFunc, location)
	if err != nil {
		return nil, fmt.Errorf("failed to decode skip delete details: %v", err)
	}
	if skipDeleteFuncOk {
		res.SkipDeleteFunction = &skipDeleteFunc.Function
	}

	// Resource Override: SerializationOnly
	res.SerializationOnly = overrides.ResourceOverride(SerializationOnly, location)

	// Resource Override: CustomSerializer
	customSerializerFunc := CustomSerializerDetails{}
	customSerializerFuncOk, err := overrides.ResourceOverrideWithDetails(CustomSerializer, &customSerializerFunc, location)
	if err != nil {
		return nil, fmt.Errorf("failed to decode custom serializer function details: %v", err)
	}
	if customSerializerFuncOk {
		res.CustomSerializer = &customSerializerFunc.Function
	}

	// Resource Override: TerraformProductName
	terraformProductName := TerraformProductNameDetails{}
	terraformProductNameOk, err := overrides.ResourceOverrideWithDetails(TerraformProductName, &terraformProductName, location)
	if err != nil {
		return nil, fmt.Errorf("failed to decode terraform product name function details: %v", err)
	}
	if terraformProductNameOk {
		scpn := SnakeCaseProductName(terraformProductName.Product)
		res.TerraformProductName = &scpn
	}

	// Resource Override: StateUpgrade
	stateUpgrade := StateUpgradeDetails{}
	stateUpgradeOk, err := overrides.ResourceOverrideWithDetails(StateUpgrade, &stateUpgrade, location)
	if err != nil {
		return nil, fmt.Errorf("Failed to decode state upgrade details: %v", err)
	}
	if stateUpgradeOk {
		res.SchemaVersion = stateUpgrade.SchemaVersion
		res.SchemaVersions = make([]int, res.SchemaVersion)
		for i := range res.SchemaVersions {
			res.SchemaVersions[i] = i
		}
	}

	if overrides.ResourceOverride(GenerateLongFormTests, location) {
		res.GenerateLongFormTests = true
	}

	res.Samples = res.loadSamples()

	return &res, nil
}