github.com/opentofu/opentofu@v1.7.1/internal/genconfig/generate_config_write.go (about) 1 // Copyright (c) The OpenTofu Authors 2 // SPDX-License-Identifier: MPL-2.0 3 // Copyright (c) 2023 HashiCorp, Inc. 4 // SPDX-License-Identifier: MPL-2.0 5 6 package genconfig 7 8 import ( 9 "fmt" 10 "io" 11 "os" 12 13 "github.com/opentofu/opentofu/internal/tfdiags" 14 ) 15 16 func ShouldWriteConfig(out string) bool { 17 // No specified out file, so don't write anything. 18 return len(out) != 0 19 } 20 21 func ValidateTargetFile(out string) (diags tfdiags.Diagnostics) { 22 if _, err := os.Stat(out); !os.IsNotExist(err) { 23 diags = diags.Append(tfdiags.Sourceless( 24 tfdiags.Error, 25 "Target generated file already exists", 26 "OpenTofu can only write generated config into a new file. Either choose a different target location or move all existing configuration out of the target file, delete it and try again.")) 27 28 } 29 return diags 30 } 31 32 type Change struct { 33 Addr string 34 ImportID string 35 GeneratedConfig string 36 } 37 38 func (c *Change) MaybeWriteConfig(writer io.Writer, out string) (io.Writer, bool, tfdiags.Diagnostics) { 39 var wroteConfig bool 40 var diags tfdiags.Diagnostics 41 if len(c.GeneratedConfig) > 0 { 42 if writer == nil { 43 // Lazily create the generated file, in case we have no 44 // generated config to create. 45 if w, err := os.Create(out); err != nil { 46 if os.IsPermission(err) { 47 diags = diags.Append(tfdiags.Sourceless( 48 tfdiags.Error, 49 "Failed to create target generated file", 50 fmt.Sprintf("OpenTofu did not have permission to create the generated file (%s) in the target directory. Please modify permissions over the target directory, and try again.", out))) 51 return nil, false, diags 52 } 53 54 diags = diags.Append(tfdiags.Sourceless( 55 tfdiags.Error, 56 "Failed to create target generated file", 57 fmt.Sprintf("OpenTofu could not create the generated file (%s) in the target directory: %v. Depending on the error message, this may be a bug in OpenTofu itself. If so, please report it!", out, err))) 58 return nil, false, diags 59 } else { 60 writer = w 61 } 62 63 header := "# __generated__ by OpenTofu\n# Please review these resources and move them into your main configuration files.\n" 64 // Missing the header from the file, isn't the end of the world 65 // so if this did return an error, then we will just ignore it. 66 _, _ = writer.Write([]byte(header)) 67 } 68 69 header := "\n# __generated__ by OpenTofu" 70 if len(c.ImportID) > 0 { 71 header += fmt.Sprintf(" from %q", c.ImportID) 72 } 73 header += "\n" 74 if _, err := writer.Write([]byte(fmt.Sprintf("%s%s\n", header, c.GeneratedConfig))); err != nil { 75 diags = diags.Append(tfdiags.Sourceless( 76 tfdiags.Warning, 77 "Failed to save generated config", 78 fmt.Sprintf("OpenTofu encountered an error while writing generated config: %v. The config for %s must be created manually before applying. Depending on the error message, this may be a bug in OpenTofu itself. If so, please report it!", err, c.Addr))) 79 } 80 wroteConfig = true 81 } 82 83 return writer, wroteConfig, diags 84 }