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
}