github.com/dahs81/otto@v0.2.1-0.20160126165905-6400716cf085/foundation/vars.go (about) 1 package foundation 2 3 import ( 4 "bufio" 5 "bytes" 6 "fmt" 7 "io" 8 "log" 9 "os" 10 "path/filepath" 11 12 "github.com/hashicorp/otto/context" 13 "github.com/hashicorp/otto/directory" 14 ) 15 16 // WriteVars will write the outputs from a foundation and put them into 17 // a key/value file within the foundation directories that is available 18 // when uploaded. This allows the build scripts to access the outputs 19 // at runtime. 20 // 21 // Ideally this sort of thing would be possible at compile-time but the 22 // values of these variables come at runtime so we need to populate this 23 // at runtime. 24 // 25 // By having a var file, it removes the burden of knowing what variables 26 // to send in to the foundation from the App implementation. They just need 27 // to call this function, upload the folder, and call main.sh. 28 func WriteVars(ctx *context.Shared) error { 29 infra := ctx.Appfile.ActiveInfrastructure() 30 if infra == nil { 31 panic("no active infra") 32 } 33 34 log.Printf("[DEBUG] infra.Foundations: %#v", infra.Foundations) 35 log.Printf("[DEBUG] ctx.FoundationDirs: %#v", ctx.FoundationDirs) 36 37 if len(ctx.FoundationDirs) < len(infra.Foundations) { 38 panic("foundationDirs is missing entries") 39 } 40 41 // subdirs are the directories to write the vars file to. For now 42 // we just write it to one but we put this here because I can see 43 // a future where more may need it. 44 subdirs := []string{"app-build"} 45 46 // Go through each foundation, grab its infrastructure data, and 47 // write it out to the proper path. 48 for i, f := range infra.Foundations { 49 entry, err := ctx.Directory.GetInfra(&directory.Infra{ 50 Lookup: directory.Lookup{Infra: infra.Type, Foundation: f.Name}}) 51 if err != nil { 52 return err 53 } 54 if entry == nil { 55 continue 56 } 57 58 // Get the var file contents into an in-memory buffer 59 var buf bytes.Buffer 60 if err := varFile(&buf, entry); err != nil { 61 return fmt.Errorf( 62 "error generating var file for %s: %s", 63 f.Name, err) 64 } 65 66 // Get a reader around the buffer so we can seek 67 r := bytes.NewReader(buf.Bytes()) 68 for _, subdir := range subdirs { 69 if _, err := r.Seek(0, 0); err != nil { 70 return err 71 } 72 73 path := filepath.Join(ctx.FoundationDirs[i], subdir) 74 if _, err := os.Stat(path); err != nil { 75 if os.IsNotExist(err) { 76 // Ignore directories that don't exist 77 continue 78 } 79 80 return err 81 } 82 path = filepath.Join(path, "vars") 83 84 log.Printf( 85 "[DEBUG] writing foundation %s var file to: %s", 86 f.Name, path) 87 w, err := os.Create(path) 88 if err != nil { 89 return err 90 } 91 _, err = io.Copy(w, r) 92 w.Close() 93 if err != nil { 94 return err 95 } 96 } 97 } 98 99 return nil 100 } 101 102 func varFile(w io.Writer, entry *directory.Infra) error { 103 bufW := bufio.NewWriter(w) 104 for k, v := range entry.Outputs { 105 _, err := bufW.WriteString(fmt.Sprintf("%s=%s\n", k, v)) 106 if err != nil { 107 return err 108 } 109 } 110 111 return bufW.Flush() 112 }