Exemple #1
0
func (g *Gaudi) copyRelativeFiles(filePath, destination string) bool {
	// File cannot be absolute
	if util.IsFile(filePath) && filePath[0] == '/' {
		util.LogError("File '" + filePath + "' cannot be an absolute path")
	}

	// Check if the relative file exists
	absolutePath := g.ApplicationDir + "/" + filePath
	if util.IsFile(absolutePath) {

		// Move file to the build context (and keep the same file tree)
		directories := strings.Split(filePath, "/")
		if len(directories) > 1 {
			os.MkdirAll(destination+strings.Join(directories[0:len(directories)-1], "/"), 0755)
		}

		err := util.Copy(destination+filePath, absolutePath)
		if err != nil {
			util.LogError(err)
		}

		return true
	}

	return false
}
Exemple #2
0
func (gaudi *Gaudi) parseTemplate(sourceDir, destinationDir string, file os.FileInfo, includes map[string]string, currentContainer *container.Container) {
	emptyCmd := shouldEmptyCmdForContainer(currentContainer.Name)
	templateData := TemplateData{gaudi.All, nil, emptyCmd}
	funcMap := template.FuncMap{
		"ToUpper": strings.ToUpper,
		"ToLower": strings.ToLower,
	}

	// Create destination directory if needed
	destination := destinationDir + currentContainer.Name + "/" + file.Name()
	if file.IsDir() {
		err := os.MkdirAll(destination, 0755)
		if err != nil {
			util.LogError(err)
		}

		return
	}

	// Read the template
	filePath := sourceDir + "/" + file.Name()
	rawContent, err := ioutil.ReadFile(filePath)
	if err != nil {
		util.LogError(err)
	}
	content := string(rawContent)

	// Add includes
	for name, include := range includes {
		content = strings.Replace(content, "[[ "+name+" ]]", include, -1)
	}

	// Parse it
	// We need to change default delimiters because sometimes we have to parse values like ${{{ .Val }}} which cause an error
	tmpl, templErr := template.New(filePath).Funcs(funcMap).Delims("[[", "]]").Parse(content)
	if templErr != nil {
		util.LogError(templErr)
	}

	templateData.Container = currentContainer
	var result bytes.Buffer
	err = tmpl.Execute(&result, templateData)
	if err != nil {
		util.LogError(err)
	}

	// Create the destination file
	ioutil.WriteFile(destination, []byte(result.String()), 0644)
}
Exemple #3
0
/**
 * Start a container as binary
 */
func Run(name, currentPath string, arguments []string, ports, environments map[string]string) {
	runFunc := reflect.ValueOf(exec.Command)
	rawArgs := []string{getDockerBinaryPath(), "run", "-v=" + currentPath + ":" + currentPath, "-w=" + currentPath}

	// Add environments
	util.Debug(environments)
	for envName, envValue := range environments {
		rawArgs = append(rawArgs, "-e="+envName+"="+envValue)
	}

	// Add ports
	for portIn, portOut := range ports {
		rawArgs = append(rawArgs, "-p="+string(portIn)+":"+string(portOut))
	}

	rawArgs = append(rawArgs, name)

	// Add user arguments
	for _, argument := range arguments {
		rawArgs = append(rawArgs, argument)
	}

	runCmd := runFunc.Call(util.BuildReflectArguments(rawArgs))[0].Interface().(*exec.Cmd)
	runCmd.Stdout = os.Stdout
	runCmd.Stdin = os.Stdin
	runCmd.Stderr = os.Stderr

	util.Debug("Run command:", runCmd.Args)

	if err := runCmd.Start(); err != nil {
		util.LogError(err)
	}
}
Exemple #4
0
func Build(name, path string) {
	buildFunc := reflect.ValueOf(exec.Command)
	rawArgs := []string{getDockerBinaryPath(), "build"}

	if *noCache {
		rawArgs = append(rawArgs, "--no-cache")
	}

	rawArgs = append(rawArgs, "-t", name, path)

	util.Debug(rawArgs)

	buildCmd := buildFunc.Call(util.BuildReflectArguments(rawArgs))[0].Interface().(*exec.Cmd)
	buildCmd.Stdin = os.Stdin

	out, err := buildCmd.CombinedOutput()
	if err != nil {
		util.Print(string(out))
		util.LogError("Error while starting container '" + name + "'")
	}

	buildCmd.Wait()

	time.Sleep(1 * time.Second)
}
Exemple #5
0
func Build(name, path string) {
	buildFunc := reflect.ValueOf(exec.Command)
	rawArgs := []string{getDockerBinaryPath(), "build"}

	if *noCache {
		rawArgs = append(rawArgs, "--no-cache")
	}

	rawArgs = append(rawArgs, "-t", name, path)

	util.Debug(rawArgs)

	buildCmd := buildFunc.Call(util.BuildReflectArguments(rawArgs))[0].Interface().(*exec.Cmd)
	buildCmd.Stderr = os.Stderr

	if !*quiet {
		buildCmd.Stdout = os.Stdout
	}

	if err := buildCmd.Run(); err != nil {
		util.LogError(err)
	}

	buildCmd.Wait()

	time.Sleep(1 * time.Second)
}
Exemple #6
0
/**
 * Start a container as a server
 */
func Start(name, image string, links []string, ports, volumes, environments map[string]string) string {
	runFunc := reflect.ValueOf(exec.Command)
	rawArgs := []string{getDockerBinaryPath(), "run", "-d", "-i", "-t", "--privileged", "--name=" + name}

	// Add environments
	util.Debug(environments)
	for envName, envValue := range environments {
		rawArgs = append(rawArgs, "-e="+envName+"="+envValue)
	}

	// Add links
	for _, link := range links {
		rawArgs = append(rawArgs, "--link="+link+":"+link)
	}

	// Add ports
	for portIn, portOut := range ports {
		rawArgs = append(rawArgs, "-p="+string(portIn)+":"+string(portOut))
	}

	// Add volumes
	for volumeHost, volumeContainer := range volumes {
		rawArgs = append(rawArgs, "-v="+volumeHost+":"+volumeContainer)
	}

	rawArgs = append(rawArgs, image)

	// Initiate the command with several arguments
	runCmd := runFunc.Call(util.BuildReflectArguments(rawArgs))[0].Interface().(*exec.Cmd)
	util.Debug("Start command:", runCmd.Args)

	out, err := runCmd.CombinedOutput()
	if err != nil {
		util.LogError(string(out))
	}

	// Inspect container to check status code
	exitCodeBuff, _ := Inspect(name, "--format", "{{.State.ExitCode}}")
	exitCode, _ := strconv.Atoi(strings.TrimSpace(string(exitCodeBuff)))

	if exitCode != 0 {
		error, _ := Logs(name)
		util.LogError("Error while starting container '" + name + "' : " + error)
	}

	return string(out)
}
Exemple #7
0
func (c *Container) RetrieveIp() {
	inspect, err := docker.Inspect(c.Id)
	if err != nil {
		util.LogError(err)
	}

	c.retrieveInfoFromInspection(inspect)
}
Exemple #8
0
func (gaudi *Gaudi) Init(content string) {
	err := goyaml.Unmarshal([]byte(content), &gaudi)
	if err != nil {
		util.LogError(err)
	}

	emptyCmdForContainers = strings.Split(*emptyCmdFlag, ",")

	// Init all containers
	gaudi.Applications.AddAmbassadors()
	gaudi.All = containerCollection.Merge(gaudi.Applications, gaudi.Binaries)
	if len(gaudi.All) == 0 {
		util.LogError("No application or binary to start. Are you missing a 'applications' or 'binaries' field in your configuration ?")
	}

	hasGaudiManagedContainer := gaudi.All.Init(gaudi.ApplicationDir)

	// Apply extends
	gaudi.applyInheritance()

	// Check if docker is installed
	if !docker.HasDocker() {
		util.LogError("Docker should be installed to use Gaudi (see: https://www.docker.io/gettingstarted/).")
	}

	// Check if base image is pulled
	if hasGaudiManagedContainer && !docker.ImageExists(DEFAULT_BASE_IMAGE) {
		util.PrintGreen("Pulling base image (this may take a few minutes) ...")

		docker.Pull(DEFAULT_BASE_IMAGE_WITH_TAG)
	}

	if gaudi.useNewVersion() {
		os.RemoveAll(TEMPLATE_DIR)
	}

	// Check if templates are present
	if !util.IsDir(TEMPLATE_DIR) {
		util.PrintGreen("Retrieving templates ...")

		retrieveTemplates()
		extractTemplates()
	}

	gaudi.build()
}
Exemple #9
0
func Remove(name string) {
	removeCmd := exec.Command(getDockerBinaryPath(), "rm", name)
	removeErr := removeCmd.Start()
	if removeErr != nil {
		util.LogError(removeErr)
	}

	time.Sleep(1 * time.Second)
}
Exemple #10
0
func Kill(name string) {

	killCommand := exec.Command(getDockerBinaryPath(), "kill", name)
	killErr := killCommand.Start()
	if killErr != nil {
		util.LogError(killErr)
	}

	time.Sleep(1 * time.Second)
}
Exemple #11
0
func (collection ContainerCollection) Init(relativePath string) bool {
	hasGaudiManagedContainer := false

	// Fill name & dependencies
	for name, currentContainer := range collection {
		currentContainer.Name = name
		currentContainer.Init()

		if currentContainer.IsGaudiManaged() {
			hasGaudiManagedContainer = true
			currentContainer.Image = "gaudi/" + name
		}

		for _, dependency := range currentContainer.Links {
			if depContainer, exists := collection[dependency]; exists {
				currentContainer.AddDependency(depContainer)
			} else {
				util.LogError(name + " references a non existing application : " + dependency)
			}
		}

		// Add relative path to volumes
		for volumeHost, volumeContainer := range currentContainer.Volumes {
			// Relative volume host
			if string(volumeHost[0]) != "/" {
				delete(currentContainer.Volumes, volumeHost)
				volumeHost = relativePath + "/" + volumeHost

				currentContainer.Volumes[volumeHost] = volumeContainer
			}

			// Create directory if needed
			if !util.IsDir(volumeHost) {
				err := os.MkdirAll(volumeHost, 0755)
				if err != nil {
					util.LogError(err)
				}
			}
		}
	}

	return hasGaudiManagedContainer
}
Exemple #12
0
func retrieveConfigPath(configFile string) string {
	if len(configFile) == 0 {
		util.LogError("Config file name cannot be empty.")
	}

	if string(configFile[0]) != "/" {
		currentDir, err := os.Getwd()
		if err != nil {
			util.LogError(err)
		}

		configFile = currentDir + "/" + configFile
	}

	if !util.IsFile(configFile) {
		util.LogError("Configuration file not found: '" + configFile + "'. Use --config to specify a custom file")
	}

	return configFile
}
Exemple #13
0
func (gaudi *Gaudi) InitFromFile(file string) {
	gaudi.ConfigurationPath = file
	gaudi.ApplicationDir = path.Dir(file)

	fileContent, err := ioutil.ReadFile(file)
	if err != nil {
		util.LogError(err)
	}

	gaudi.Init(string(fileContent))
}
Exemple #14
0
func retrieveTemplates() {
	os.MkdirAll(TEMPLATE_DIR, 0755)

	archive, err := os.Create(TEMPLATE_DIR + "templates.tar")
	if err != nil {
		util.LogError(err)
	}
	defer archive.Close()

	content, err := http.Get(TEMPLATE_REMOTE_PATH)
	if err != nil {
		util.LogError(err)
	}
	defer content.Body.Close()

	_, err = io.Copy(archive, content.Body)
	if err != nil {
		util.LogError(err)
	}
}
Exemple #15
0
func extractTemplates() {
	tarFile, _ := os.Open(TEMPLATE_DIR + "templates.tar")
	defer tarFile.Close()

	tar := tar.NewReader(tarFile)

	for {
		header, err := tar.Next()
		if err == io.EOF {
			break
		}

		if err != nil {
			util.LogError(err)
		}

		// Remove first path part
		filePath := strings.Join(strings.Split(header.Name, "/")[1:], "/")

		// Check if we should create a folder or a file
		if header.Size == 0 {
			err := os.MkdirAll(TEMPLATE_DIR+filePath, 0755)
			if err != nil {
				util.LogError(err)
			}
		} else {
			f, err := os.Create(TEMPLATE_DIR + filePath)
			if err != nil {
				util.LogError(err)
			}
			defer f.Close()

			_, err = io.Copy(f, tar)
			if err != nil {
				util.LogError(err)
			}
		}
	}

	os.Remove(TEMPLATE_DIR + "templates.tar")
}
Exemple #16
0
func Pull(name string) {
	pullCmd := exec.Command(getDockerBinaryPath(), "pull", name)
	pullCmd.Stderr = os.Stderr
	pullCmd.Stdin = os.Stdin

	util.Debug("Pull command:", pullCmd.Args)

	if err := pullCmd.Run(); err != nil {
		util.LogError(err)
	}

	pullCmd.Wait()
}
Exemple #17
0
func startOne(currentContainer *container.Container, rebuild bool, done map[string]chan bool) {
	// Waiting for dependencies to be started
	for _, dependency := range currentContainer.Dependencies {
		if dependency.Name == currentContainer.Name {
			util.LogError("Application " + currentContainer.Name + " can't be linked with itself.")
		}

		<-done[dependency.Name]
	}

	currentContainer.Start(rebuild)

	close(done[currentContainer.Name])
}
Exemple #18
0
func Enter(name string) {
	var pid string
	var imageExists bool
	nsenter, _ := exec.LookPath("nsenter")

	ps, _ := SnapshotProcesses()
	if pid, imageExists = ps[name]; !imageExists {
		util.LogError("Image " + name + " doesn't exists")
	}

	statePidBuff, _ := Inspect(pid, "--format", "{{.State.Pid}}")
	statePid := strings.TrimSpace(string(statePidBuff))

	enterCmd := exec.Command("sudo", nsenter, "--target", statePid, "--mount", "--uts", "--ipc", "--net", "--pid")
	enterCmd.Stdout = os.Stdout
	enterCmd.Stdin = os.Stdin
	enterCmd.Stderr = os.Stderr

	util.Debug("Run command:", enterCmd.Args)

	if err := enterCmd.Run(); err != nil {
		util.LogError(err)
	}
}
Exemple #19
0
/**
 * Enter in a specific container
 */
func (gaudi *Gaudi) Enter(name string) {
	// Check if nsenter exists
	images, err := docker.GetImages()
	if err != nil {
		util.LogError(err)
	}

	if _, ok := images["jpetazzo/nsenter"]; !ok {
		// Pull ns-enter image
		util.PrintGreen("Retrieving ns-enter image ...")
		docker.Exec([]string{"run", "--rm", "-v", "/usr/local/bin:/target", "jpetazzo/nsenter"}, false)
	}

	container := gaudi.All[name]
	docker.Enter(container.GetFullName())
}
Exemple #20
0
func Exec(args []string, hasStdout bool) {
	execFunc := reflect.ValueOf(exec.Command)
	execCmd := execFunc.Call(util.BuildReflectArguments(args))[0].Interface().(*exec.Cmd)

	if hasStdout {
		execCmd.Stdout = os.Stdout
	}

	execCmd.Stdin = os.Stdin
	execCmd.Stderr = os.Stderr

	util.Debug("Exec command:", execCmd.Args)

	if err := execCmd.Start(); err != nil {
		util.LogError(err)
	}
}
Exemple #21
0
/**
 * Check if all applications are started
 */
func (gaudi *Gaudi) Check() {
	images, err := docker.SnapshotProcesses()
	if err != nil {
		util.LogError(err)
	}

	for _, currentContainer := range gaudi.Applications {
		if containerId, ok := images[currentContainer.Image]; ok {
			currentContainer.Id = containerId
			currentContainer.RetrieveIp()

			util.PrintOrange("Application", currentContainer.Name, "is running", "("+currentContainer.Ip+":"+currentContainer.GetFirstPort()+")")
		} else {
			util.PrintOrange("Application", currentContainer.Name, "is not running")
		}
	}
}
Exemple #22
0
func getIncludes() map[string]string {
	includesDir := TEMPLATE_DIR + "_includes/"
	result := make(map[string]string)

	files, err := ioutil.ReadDir(includesDir)
	if err != nil {
		util.LogError(err)
	}

	for _, file := range files {
		name := strings.Split(file.Name(), ".")[0]
		content, _ := ioutil.ReadFile(includesDir + file.Name())

		result[name] = string(content)
	}

	return result
}
Exemple #23
0
func main() {
	flag.Parse()

	if *flagVersion {
		fmt.Println(gaudi.VERSION)
		return
	}

	rebuild := len(flag.Args()) > 0 && flag.Args()[0] == "rebuild"
	g := gaudi.Gaudi{}
	g.InitFromFile(retrieveConfigPath(*config))

	if len(flag.Args()) == 0 || rebuild {
		// Start all applications
		g.StartApplications(rebuild)
	} else {
		switch os.Args[1] {
		case "run":
			// Run a specific command
			g.Run(os.Args[2], os.Args[3:])
			break
		case "enter":
			// Enter in a specific container
			g.Enter(os.Args[2])
			break
		case "stop":
			// Stop all applications
			g.StopApplications()
			break
		case "check":
			// Check if all applications are running
			g.Check()
			break
		case "clean":
			// Clean application containers
			g.Clean()
			break
		default:
			util.LogError("Argument " + os.Args[1] + " was not found")
			break
		}
	}
}
Exemple #24
0
/**
 * Start a container as a server
 */
func Start(name, image string, links []string, ports, volumes, environments map[string]string) string {
	runFunc := reflect.ValueOf(exec.Command)
	rawArgs := []string{getDockerBinaryPath(), "run", "-d", "-i", "-t", "--privileged", "--name=" + name}

	// Add environments
	util.Debug(environments)
	for envName, envValue := range environments {
		rawArgs = append(rawArgs, "-e="+envName+"="+envValue)
	}

	// Add links
	for _, link := range links {
		rawArgs = append(rawArgs, "--link="+link+":"+link)
	}

	// Add ports
	for portIn, portOut := range ports {
		rawArgs = append(rawArgs, "-p="+string(portIn)+":"+string(portOut))
	}

	// Add volumes
	for volumeHost, volumeContainer := range volumes {
		rawArgs = append(rawArgs, "-v="+volumeHost+":"+volumeContainer)
	}

	rawArgs = append(rawArgs, image)

	// Initiate the command with several arguments
	runCmd := runFunc.Call(util.BuildReflectArguments(rawArgs))[0].Interface().(*exec.Cmd)
	util.Debug("Start command:", runCmd.Args)

	out, err := runCmd.CombinedOutput()
	if err != nil {
		util.LogError(string(out))
	}

	return string(out)
}
Exemple #25
0
func (gaudi *Gaudi) applyInheritance() {
	extendsChan := make(map[string]chan bool)

	for name, currentContainer := range gaudi.Applications {
		extendsChan[name] = make(chan bool)

		if currentContainer.Extends == "" {
			close(extendsChan[name])
			continue
		}

		if parentContainer, exists := gaudi.All[currentContainer.Extends]; exists {
			go extendsOne(currentContainer, parentContainer, extendsChan)
		} else {
			util.LogError(currentContainer.Name + " extends a non existing application : " + currentContainer.Extends)
		}
	}

	// Waiting for all applications to be extended
	for name, _ := range extendsChan {
		<-extendsChan[name]
	}
}
Exemple #26
0
func (collection ContainerCollection) CheckIfNotEmpty() {
	// Check if there is at least a container
	if collection == nil || len(collection) == 0 {
		util.LogError("Gaudi requires at least an application to be defined to start anything")
	}
}
Exemple #27
0
func (gaudi *Gaudi) build() {
	// Retrieve application Path
	currentDirctory, _ := os.Getwd()

	err := os.MkdirAll(PARSED_TEMPLATE_DIR, 0700)
	if err != nil {
		util.LogError(err)
	}

	// Retrieve includes
	includes := getIncludes()

	for _, currentContainer := range gaudi.All {
		// Check if the container has a type
		if currentContainer.Type == "" {
			util.LogError("Container " + currentContainer.Name + " should have a field called 'type'.")
		}

		if !currentContainer.IsGaudiManaged() {
			continue
		}

		// Check if the beforeScript is a file
		beforeScript := currentContainer.BeforeScript
		if len(beforeScript) != 0 {
			copied := gaudi.copyRelativeFiles(beforeScript, PARSED_TEMPLATE_DIR+currentContainer.Name+"/")
			if copied {
				currentContainer.BeforeScript = "./" + currentContainer.BeforeScript
			}
		}

		// Check if the afterScript is a file
		afterScript := currentContainer.AfterScript
		if len(afterScript) != 0 {
			copied := gaudi.copyRelativeFiles(afterScript, PARSED_TEMPLATE_DIR+currentContainer.Name+"/")
			if copied {
				currentContainer.AfterScript = "./" + currentContainer.AfterScript
			}
		}

		templateDir, isCustom := gaudi.GetContainerTemplate(currentContainer)

		files, err := ioutil.ReadDir(templateDir)
		if err != nil {
			util.LogError("Application '" + currentContainer.Type + "' is not supported. Check http://gaudi.io/components.html for a list of supported applications.")
		}

		err = os.MkdirAll(PARSED_TEMPLATE_DIR+currentContainer.Name, 0755)
		if err != nil {
			util.LogError(err)
		}

		sourceTemplateDir := TEMPLATE_DIR + currentContainer.Type
		if isCustom {
			sourceTemplateDir = templateDir
		}

		// Parse & copy files
		for _, file := range files {
			gaudi.parseTemplate(sourceTemplateDir, PARSED_TEMPLATE_DIR, file, includes, currentContainer)
		}

		// Copy all files marked as Add
		for fileToAdd := range currentContainer.Add {
			filePath := currentDirctory + "/" + fileToAdd

			directories := strings.Split(fileToAdd, "/")
			if len(directories) > 1 {
				os.MkdirAll(PARSED_TEMPLATE_DIR+currentContainer.Name+"/"+strings.Join(directories[0:len(directories)-1], "/"), 0755)
			}

			err := util.Copy(PARSED_TEMPLATE_DIR+currentContainer.Name+"/"+fileToAdd, filePath)
			if err != nil {
				util.LogError(err)
			}
		}
	}
}