github.com/crossplane/upjet@v1.3.0/pkg/terraform/timeouts.go (about) 1 // SPDX-FileCopyrightText: 2023 The Crossplane Authors <https://crossplane.io> 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 5 package terraform 6 7 import ( 8 "github.com/crossplane/crossplane-runtime/pkg/errors" 9 10 "github.com/crossplane/upjet/pkg/config" 11 "github.com/crossplane/upjet/pkg/resource/json" 12 ) 13 14 // "e2bfb730-ecaa-11e6-8f88-34363bc7c4c0" is a hardcoded string for Terraform 15 // timeout key in private raw, i.e. provider specific metadata: 16 // https://github.com/hashicorp/terraform-plugin-sdk/blob/112e2164c381d80e8ada3170dac9a8a5db01079a/helper/schema/resource_timeout.go#L14 17 const tfMetaTimeoutKey = "e2bfb730-ecaa-11e6-8f88-34363bc7c4c0" 18 19 type timeouts config.OperationTimeouts 20 21 func (ts timeouts) asParameter() map[string]string { 22 param := make(map[string]string) 23 if t := ts.Read.String(); t != "0s" { 24 param["read"] = t 25 } 26 if t := ts.Create.String(); t != "0s" { 27 param["create"] = t 28 } 29 if t := ts.Update.String(); t != "0s" { 30 param["update"] = t 31 } 32 if t := ts.Delete.String(); t != "0s" { 33 param["delete"] = t 34 } 35 return param 36 } 37 38 func (ts timeouts) asMetadata() map[string]any { 39 // See how timeouts encoded as metadata on Terraform side: 40 // https://github.com/hashicorp/terraform-plugin-sdk/blob/112e2164c381d80e8ada3170dac9a8a5db01079a/helper/schema/resource_timeout.go#L170 41 meta := make(map[string]any) 42 if t := ts.Read.String(); t != "0s" { 43 meta["read"] = ts.Read.Nanoseconds() 44 } 45 if t := ts.Create.String(); t != "0s" { 46 meta["create"] = ts.Create.Nanoseconds() 47 } 48 if t := ts.Update.String(); t != "0s" { 49 meta["update"] = ts.Update.Nanoseconds() 50 } 51 if t := ts.Delete.String(); t != "0s" { 52 meta["delete"] = ts.Delete.Nanoseconds() 53 } 54 return meta 55 } 56 57 func insertTimeoutsMeta(existingMeta []byte, to timeouts) ([]byte, error) { 58 customTimeouts := to.asMetadata() 59 if len(customTimeouts) == 0 { 60 // No custom timeout configured, nothing to do. 61 return existingMeta, nil 62 } 63 meta := make(map[string]any) 64 if len(existingMeta) == 0 { 65 // No existing data, just initialize a new meta with custom timeouts. 66 meta[tfMetaTimeoutKey] = customTimeouts 67 return json.JSParser.Marshal(meta) 68 } 69 // There are some existing metadata, let's parse it to insert custom 70 // timeouts properly. 71 if err := json.JSParser.Unmarshal(existingMeta, &meta); err != nil { 72 return nil, errors.Wrap(err, "cannot parse existing metadata") 73 } 74 if existingTimeouts, ok := meta[tfMetaTimeoutKey].(map[string]any); ok { 75 // There are some timeout configuration exists in existing metadata. 76 // Only override custom timeouts. 77 for k, v := range customTimeouts { 78 existingTimeouts[k] = v 79 } 80 return json.JSParser.Marshal(meta) 81 } 82 // No existing timeout configuration, initialize it with custom timeouts. 83 meta[tfMetaTimeoutKey] = customTimeouts 84 return json.JSParser.Marshal(meta) 85 }