github.com/skippbox/kompose-origin@v0.0.0-20160524133224-16a9dca7bac2/project/context.go (about)

     1  package project
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"path"
     8  	"path/filepath"
     9  	"regexp"
    10  	"strings"
    11  
    12  	"github.com/Sirupsen/logrus"
    13  	"github.com/docker/libcompose/config"
    14  	"github.com/docker/libcompose/logger"
    15  )
    16  
    17  var projectRegexp = regexp.MustCompile("[^a-zA-Z0-9_.-]")
    18  
    19  // Context holds context meta information about a libcompose project, like
    20  // the project name, the compose file, etc.
    21  type Context struct {
    22  	ComposeFiles        []string
    23  	ComposeBytes        [][]byte
    24  	ProjectName         string
    25  	isOpen              bool
    26  	ServiceFactory      ServiceFactory
    27  	EnvironmentLookup   config.EnvironmentLookup
    28  	ResourceLookup      config.ResourceLookup
    29  	LoggerFactory       logger.Factory
    30  	IgnoreMissingConfig bool
    31  	Project             *Project
    32  }
    33  
    34  func (c *Context) readComposeFiles() error {
    35  	if c.ComposeBytes != nil {
    36  		return nil
    37  	}
    38  
    39  	logrus.Debugf("Opening compose files: %s", strings.Join(c.ComposeFiles, ","))
    40  
    41  	// Handle STDIN (`-f -`)
    42  	if len(c.ComposeFiles) == 1 && c.ComposeFiles[0] == "-" {
    43  		composeBytes, err := ioutil.ReadAll(os.Stdin)
    44  		if err != nil {
    45  			logrus.Errorf("Failed to read compose file from stdin: %v", err)
    46  			return err
    47  		}
    48  		c.ComposeBytes = [][]byte{composeBytes}
    49  		return nil
    50  	}
    51  
    52  	for _, composeFile := range c.ComposeFiles {
    53  		composeBytes, err := ioutil.ReadFile(composeFile)
    54  		if err != nil && !os.IsNotExist(err) {
    55  			logrus.Errorf("Failed to open the compose file: %s", composeFile)
    56  			return err
    57  		}
    58  		if err != nil && !c.IgnoreMissingConfig {
    59  			logrus.Errorf("Failed to find the compose file: %s", composeFile)
    60  			return err
    61  		}
    62  		c.ComposeBytes = append(c.ComposeBytes, composeBytes)
    63  	}
    64  
    65  	return nil
    66  }
    67  
    68  func (c *Context) determineProject() error {
    69  	name, err := c.lookupProjectName()
    70  	if err != nil {
    71  		return err
    72  	}
    73  
    74  	c.ProjectName = normalizeName(name)
    75  
    76  	if c.ProjectName == "" {
    77  		return fmt.Errorf("Falied to determine project name")
    78  	}
    79  
    80  	return nil
    81  }
    82  
    83  func (c *Context) lookupProjectName() (string, error) {
    84  	if c.ProjectName != "" {
    85  		return c.ProjectName, nil
    86  	}
    87  
    88  	if envProject := os.Getenv("COMPOSE_PROJECT_NAME"); envProject != "" {
    89  		return envProject, nil
    90  	}
    91  
    92  	file := "."
    93  	if len(c.ComposeFiles) > 0 {
    94  		file = c.ComposeFiles[0]
    95  	}
    96  
    97  	f, err := filepath.Abs(file)
    98  	if err != nil {
    99  		logrus.Errorf("Failed to get absolute directory for: %s", file)
   100  		return "", err
   101  	}
   102  
   103  	f = toUnixPath(f)
   104  
   105  	parent := path.Base(path.Dir(f))
   106  	if parent != "" && parent != "." {
   107  		return parent, nil
   108  	} else if wd, err := os.Getwd(); err != nil {
   109  		return "", err
   110  	} else {
   111  		return path.Base(toUnixPath(wd)), nil
   112  	}
   113  }
   114  
   115  func normalizeName(name string) string {
   116  	r := regexp.MustCompile("[^a-z0-9]+")
   117  	return r.ReplaceAllString(strings.ToLower(name), "")
   118  }
   119  
   120  func toUnixPath(p string) string {
   121  	return strings.Replace(p, "\\", "/", -1)
   122  }
   123  
   124  func (c *Context) open() error {
   125  	if c.isOpen {
   126  		return nil
   127  	}
   128  
   129  	if err := c.readComposeFiles(); err != nil {
   130  		return err
   131  	}
   132  
   133  	if err := c.determineProject(); err != nil {
   134  		return err
   135  	}
   136  
   137  	c.isOpen = true
   138  	return nil
   139  }