github.com/searchspring/haus@v0.1.8-0.20200414161854-a7ca8bb9ea93/app/haus.go (about) 1 // Package haus reads a yaml file describing docker architecture and 2 // generates from templates docker-compose and RepoTsar files. 3 package haus 4 5 import( 6 "fmt" 7 "os" 8 "strings" 9 "time" 10 ) 11 12 // Haus represents an instance of the haus application. 13 type Haus struct{ 14 Config Config 15 } 16 17 type semaphore chan error 18 19 // Run starts the process of the haus application and returns error. 20 func (h *Haus) Run() error { 21 c := h.Config 22 23 repotsaryml := &RepoYml{ 24 Signature: Signature{ 25 Name: c.Name, 26 Email: c.Email, 27 }, 28 } 29 dockeryml := &DockerYml{} 30 // Create environments 31 thrnum := len(c.Environments) 32 sem := make(semaphore, thrnum) 33 for k := range c.Environments { 34 // Thread environment creatation 35 go h.createEnv(k,dockeryml,repotsaryml,sem) 36 // Sleep between thread creation so git doesn't step on it's self 37 time.Sleep(50 * time.Millisecond) 38 39 } 40 // Wait for threads to finish 41 for i := 0; i < thrnum; i++ { 42 err := <-sem 43 if err != nil { 44 return err 45 } 46 } 47 48 // Create Yaml files 49 _,err := repotsaryml.WriteYml(c.Path+"/repotsar.yml") 50 if err != nil { 51 return err 52 } 53 _,err = dockeryml.WriteYml(c.Path+"/docker-compose.yml") 54 if err != nil { 55 return err 56 } 57 return nil 58 59 } 60 61 // createEnv create a single environment define in the haus config. Returns error. 62 func (h *Haus) createEnv(env string, dockeryml *DockerYml, repotsaryml *RepoYml, sem semaphore) error { 63 // check requirements 64 e := h.Config.Environments[env] 65 for _,v := range e.Requirements { 66 if _, ok := h.Config.Environments[v]; ok != true { 67 err := fmt.Errorf("%#v requires %#v and it is not defined.",env,v) 68 sem <-err 69 return err 70 } 71 } 72 name,version := nameSplit(env) 73 // Create Cfgs from templates 74 tmpl := &Template{ 75 Path: h.Config.Path, 76 Pwd: h.Config.Pwd, 77 Name: name, 78 Branch: version, 79 Version: version, 80 Variables: e.Variables, 81 Env: envMap(), 82 } 83 84 // Extract RepoTsar Cfgs from template 85 repos,err := tmpl.RepoTsarCfgs() 86 if err != nil { 87 sem <-err 88 return err 89 } 90 // Extract Docker Cfgs from template 91 docker,err := tmpl.DockerCfgs() 92 if err != nil { 93 sem <-err 94 return err 95 } 96 97 // Clone docker build repos first to ensure they are cloned into 98 // empty directories 99 for dkey,dval := range docker { 100 if dval.Build != "" { 101 repo := repos[dkey] 102 err = repo.CloneRepo(dkey) 103 if err != nil { 104 sem <-err 105 return err 106 } 107 err = repo.CreateLink() 108 if err != nil { 109 sem <-err 110 return err 111 } 112 113 } 114 } 115 // Clone other repos after cloning docker build repos 116 for rkey,rval := range repos { 117 if _,ok := docker[rkey]; ok { 118 } else { 119 err = rval.CloneRepo(rkey) 120 if err != nil { 121 sem <-err 122 return err 123 } 124 err = rval.CreateLink() 125 if err != nil { 126 sem <-err 127 return err 128 } 129 } 130 } 131 // Add Cfgs 132 dockeryml.AddCfg(docker) 133 repotsaryml.AddCfg(repos) 134 sem <-nil 135 return nil 136 } 137 138 // nameSplit splits string with _ into two strings if there's a '_'. 139 func nameSplit(n string) (string, string) { 140 // split name and version or branch 141 s := strings.Split(n,"_") 142 var version string 143 var name string 144 if len(s) > 1 { 145 name, version = s[0], s[1] 146 } else { 147 name = s[0] 148 } 149 return name, version 150 } 151 152 // envMap returns a map[string]string of Environment variables 153 func envMap() map[string]string { 154 env := make(map[string]string) 155 envstrings := os.Environ() 156 for i := range envstrings { 157 kv := strings.Split(envstrings[i],"=") 158 env[kv[0]] = kv[1] 159 } 160 return env 161 }