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  }