예제 #1
0
// Is this project configured enough to run coach
func (project *Project) IsValid(logger log.Log) bool {
	/**
	 * 1. do we have a project coach folder, and does it exist.
	 */
	if projectCoachPath, ok := project.Path("project-coach"); ok {
		if _, err := os.Stat(projectCoachPath); err != nil {
			logger.Warning(`Could not find a project root .coach folder:  
- At the root of any coach prpject, must be a .coach folder;
- This folder can container project configurations;
- The folder is required, because it tells coach where the project base is.`)
			return false
		}
	} else {
		return false
	}

	/**
	 * 2. Do we have a project name
	 *
	 * This is important as it gets used to make image and container names
	 */
	if project.Name == "" {
		logger.Warning(`Coach project has no Name.  
- A project name can be set in the .coach/conf.yml file.  
- The Name is used as a base for image and container names.`)
		return false
	}

	return true
}
예제 #2
0
파일: node.go 프로젝트: james-nesbitt/coach
// Constructor for BaseNode
func (node *BaseNode) Init(logger log.Log, name string, project *conf.Project, client Client, instancesSettings InstancesSettings) bool {
	node.log = logger
	node.conf = project
	node.name = name
	node.client = client
	node.manualDependencies = []string{}

	instancesMachineName := node.MachineName()

	settingsInterface := instancesSettings.Settings()
	switch settingsInterface.(type) {
	case FixedInstancesSettings:
		node.instances = Instances(&FixedInstances{})
		instancesMachineName += "_fixed_"
	case TemporaryInstancesSettings:
		node.instances = Instances(&TemporaryInstances{})
		instancesMachineName += "_temp_"
	case ScaledInstancesSettings:
		node.instances = Instances(&ScaledInstances{})
		instancesMachineName += "_scaled_"
	case SingleInstancesSettings:
		node.instances = Instances(&SingleInstances{})
	default:
		node.instances = Instances(&SingleInstances{})
	}

	node.instances.Init(logger, instancesMachineName, client, instancesSettings)

	logger.Debug(log.VERBOSITY_DEBUG_STAAAP, "Built new node:", node.client)
	return true
}
예제 #3
0
// scale a node up a certain number of instances
func (operation *ScaleOperation) ScaleUpNumber(logger log.Log, instances libs.Instances, number int) int {
	count := 0
	instancesOrder := instances.InstancesOrder()

InstanceScaleReturn:
	for _, instanceId := range instancesOrder {
		if instance, ok := instances.Instance(instanceId); ok {
			client := instance.Client()

			if client.IsRunning() {
				continue InstanceScaleReturn
			} else if !client.HasContainer() {
				// create a new container for this instance
				client.Create(logger, []string{}, false)
			}

			logger.Info("Node Scaling up. Starting instance :" + instanceId)
			client.Start(logger, false)

			count++
			if count >= number {
				return count
			}
		}
	}

	return count
}
예제 #4
0
func (client *FSouza_InstanceClient) Commit(logger log.Log, tag string, message string) bool {
	id := client.instance.MachineName()
	config := client.settings.Config
	repo := client.settings.Repository
	author := client.settings.Author

	if repo == "" {
		repo, _ = client.GetImageName()
	}

	options := docker.CommitContainerOptions{
		Container:  id,
		Repository: repo,
		Tag:        tag,
		Run:        &config,
	}

	if message != "" {
		options.Message = message
	}
	if author != "" {
		author = client.conf.Author
	}

	_, err := client.backend.CommitContainer(options)
	if err != nil {
		logger.Warning("Failed to commit container changes to an image [" + client.instance.Id() + ":" + id + "] : " + tag)
		return false
	} else {
		client.backend.Refresh(true, false)
		logger.Message("Committed container changes to an image [" + client.instance.Id() + ":" + id + "] : " + tag)
		return true
	}
}
예제 #5
0
// scale a node down a certain number of instances
func (operation *ScaleOperation) ScaleDownNumber(logger log.Log, instances libs.Instances, number int) int {

	count := 0
	instancesOrder := []string{}
	for _, instanceId := range instances.InstancesOrder() {
		instancesOrder = append([]string{instanceId}, instancesOrder...)
	}

InstanceScaleReturn:
	for _, instanceId := range instancesOrder {
		if instance, ok := instances.Instance(instanceId); ok {
			client := instance.Client()

			if !client.IsRunning() {
				continue InstanceScaleReturn
			}

			logger.Info("Node Scaling down. Stopping instance :" + instanceId)
			client.Stop(logger, operation.force, operation.timeout)

			if operation.removeStopped {
				client.Remove(logger, operation.force)
			}

			count++
			if count >= number {
				return count
			}
		}
	}

	return count
}
예제 #6
0
func (node *PullNode) Init(logger log.Log, name string, project *conf.Project, client Client, instancesSettings InstancesSettings) bool {
	node.BaseNode.Init(logger, name, project, client, instancesSettings)

	settingsInterface := instancesSettings.Settings()
	switch settingsInterface.(type) {
	case FixedInstancesSettings:
		logger.Warning("Pull node cannot be configured to use fixed instances.  Using null instance instead.")
		node.defaultInstances(logger, client, instancesSettings)
	case ScaledInstancesSettings:
		logger.Warning("Pull node cannot be configured to use scaled instances.  Using null instance instead.")
		node.defaultInstances(logger, client, instancesSettings)
	case SingleInstancesSettings:
		logger.Warning("Pull node cannot be configured to use single instances.  Using null instance instead.")
		node.defaultInstances(logger, client, instancesSettings)
	case TemporaryInstancesSettings:
		logger.Warning("Pull node cannot be configured to use disposable instances.  Using null instance instead.")
		node.defaultInstances(logger, client, instancesSettings)
	default:
		node.defaultInstances(logger, client, instancesSettings)
	}

	node.instances.Init(logger, node.MachineName(), client, instancesSettings)

	logger.Debug(log.VERBOSITY_DEBUG_STAAAP, "Built new node:", node.client)
	return true
}
예제 #7
0
파일: demo.go 프로젝트: james-nesbitt/coach
func (tasks *InitTasks) Init_Demo_Run(logger log.Log, demo string) bool {
	if demoPath, ok := COACH_DEMO_URLS[demo]; ok {
		return tasks.Init_Yaml_Run(logger, demoPath)
	} else {
		logger.Error("Unknown demo key : " + demo)
		return false
	}
}
예제 #8
0
파일: file.go 프로젝트: james-nesbitt/coach
func (task *InitTaskFileBase) CopyFileRecursive(logger log.Log, path string, source string) bool {
	sourceAbsPath, ok := task.absolutePath(source, false)
	if !ok {
		logger.Warning("Couldn't find copy source " + source)
		return false
	}
	return task.copyFileRecursive(logger, path, sourceAbsPath, "")
}
예제 #9
0
// Use the secrets yaml object to configure a project
func (secrets *secrets_Yaml) configureProject(logger log.Log, project *Project) bool {
	for key, value := range secrets.Secrets {
		project.SetToken(key, value)
	}

	logger.Debug(log.VERBOSITY_DEBUG_STAAAP, "Configured project from YAML secrets")
	return true
}
예제 #10
0
func (operation *UnknownOperation) Run(logger log.Log) bool {
	if operation.id == DEFAULT_OPERATION {
		logger.Error("No operation specified")
	} else {
		logger.Error("Unknown operation: " + operation.id)
	}
	return false
}
예제 #11
0
// Run all of the prepared operations
func (operations *Operations) Run(logger log.Log) {
	if len(operations.operationsList) == 0 {
		logger.Error("No operation created")
	} else {
		for _, operation := range operations.operationsList {
			operation.Run(logger.MakeChild(operation.Id()))
		}
	}
}
예제 #12
0
// Try to configure a project by parsing yaml from a byte stream
func (project *Project) from_ConfYamlBytes(logger log.Log, yamlBytes []byte) bool {
	// parse the config file contents as a ConfSource_projectyaml object
	source := new(conf_Yaml)
	if err := yaml.Unmarshal(yamlBytes, source); err != nil {
		logger.Warning("YAML parsing error : " + err.Error())
		return false
	}
	logger.Debug(log.VERBOSITY_DEBUG_STAAAP, "YAML source:", *source)

	return source.configureProject(logger, project)
}
예제 #13
0
func (instances *SingleInstances) Prepare(logger log.Log, client Client, nodes *Nodes, node Node) bool {
	instances.log = logger
	logger.Debug(log.VERBOSITY_DEBUG_WOAH, "Prepare: Single Instances")

	instances.instance = SingleInstance{}
	instances.instance.Init(logger, INSTANCE_SINGLE_ID, instances.MachineName(), client, true)

	instances.log.Debug(log.VERBOSITY_DEBUG_WOAH, "Created single instance", instances.instance)

	return true
}
예제 #14
0
파일: file.go 프로젝트: james-nesbitt/coach
func (task *InitTaskFileBase) copyFileRecursive(logger log.Log, destinationRootPath string, sourceRootPath string, sourcePath string) bool {
	fullPath := sourceRootPath

	if sourcePath != "" {
		fullPath = path.Join(fullPath, sourcePath)
	}

	// get properties of source dir
	info,
		err := os.Stat(fullPath)
	if err != nil {
		// @TODO do something log : source doesn't exist
		logger.Warning("File does not exist :" + fullPath)
		return false
	}

	mode := info.Mode()
	if mode.IsDir() {

		directory, _ := os.Open(fullPath)
		objects, err := directory.Readdir(-1)

		if err != nil {
			// @TODO do something log : source doesn't exist
			logger.Warning("Could not open directory")
			return false
		}

		for _, obj := range objects {

			//childSourcePath := source + "/" + obj.Name()
			childSourcePath := path.Join(sourcePath, obj.Name())
			if !task.copyFileRecursive(logger, destinationRootPath, sourceRootPath, childSourcePath) {
				logger.Warning("Resursive copy failed")
			}

		}

	} else {
		// add file copy
		destinationPath := path.Join(destinationRootPath, sourcePath)
		if task.CopyFile(logger, destinationPath, sourceRootPath) {
			logger.Info("--> Copied file (recursively): " + sourcePath + " [from " + sourceRootPath + "]")
			return true
		} else {
			logger.Warning("--> Failed to copy file: " + sourcePath + " [from " + sourceRootPath + "]")
			return false
		}
		return true
	}
	return true
}
예제 #15
0
func (client *FSouza_InstanceClient) Stop(logger log.Log, force bool, timeout uint) bool {
	id := client.instance.MachineName()

	err := client.backend.StopContainer(id, timeout)
	if err != nil {
		logger.Error("Failed to stop node container [" + id + "] => " + err.Error())
		return false
	} else {
		client.backend.Refresh(false, true)
		logger.Message("Node instance stopped [" + id + "]")
		return true
	}
}
예제 #16
0
func (client *FSouza_InstanceClient) Unpause(logger log.Log) bool {
	id := client.instance.MachineName()

	err := client.backend.UnpauseContainer(id)
	if err != nil {
		logger.Error("Failed to unpause Instance [" + client.instance.Id() + "] Container [" + id + "] =>" + err.Error())
		return false
	} else {
		client.backend.Refresh(false, true)
		logger.Message("Unpaused Instance [" + client.instance.Id() + "] Container [" + id + "]")
		return true
	}
}
예제 #17
0
파일: file.go 프로젝트: james-nesbitt/coach
func (task *InitTaskFileCopy) RunTask(logger log.Log) bool {
	if task.path == "" || task.root == "" || task.source == "" {
		return false
	}

	if task.CopyFileRecursive(logger, task.path, task.source) {
		logger.Message("--> Copied file : " + task.source + " -> " + task.path)
		return true
	} else {
		logger.Warning("--> Failed to copy file : " + task.source + " -> " + task.path)
		return false
	}
}
예제 #18
0
파일: file.go 프로젝트: james-nesbitt/coach
func (task *InitTaskFile) RunTask(logger log.Log) bool {
	if task.path == "" {
		return false
	}

	if task.MakeFile(logger, task.path, task.contents) {
		logger.Message("--> Created file : " + task.path)
		return true
	} else {
		logger.Warning("--> Failed to create file : " + task.path)
		return false
	}
}
예제 #19
0
파일: file.go 프로젝트: james-nesbitt/coach
func (task *InitTaskRemoteFile) RunTask(logger log.Log) bool {
	if task.path == "" || task.root == "" || task.url == "" {
		return false
	}

	if task.CopyRemoteFile(logger, task.path, task.url) {
		logger.Message("--> Copied remote file : " + task.url + " -> " + task.path)
		return true
	} else {
		logger.Warning("--> Failed to copy remote file : " + task.url)
		return false
	}
}
예제 #20
0
func (operation *InitGenerateOperation) Run(logger log.Log) bool {
	logger.Info("running init operation:" + operation.output)

	var writer io.Writer
	switch operation.output {
	case "logger":
		fallthrough
	case "":
		writer = logger
	default:
		if strings.HasSuffix(operation.output, ".") {
			operation.output = operation.output + operation.handler
		}
		if fileWriter, err := os.Create(operation.output); err == nil {
			operation.skip = append(operation.skip, operation.output)
			writer = io.Writer(fileWriter)
			defer fileWriter.Close()
			logger.Message("Opening file for init generation output: " + operation.output)
		} else {
			logger.Error("Could not open output file to write init to:" + operation.output)
		}
	}

	initialize.Init_Generate(logger.MakeChild("init-generate"), operation.handler, operation.root, operation.skip, operation.sizeLimit, writer)

	return true
}
예제 #21
0
func (operation *StatusOperation) Run(logger log.Log) bool {
	logger.Message("RUNNING Status OPERATION")

	logger.Debug(log.VERBOSITY_DEBUG, "Run:Targets", operation.targets.TargetOrder())
	for _, targetID := range operation.targets.TargetOrder() {
		target, targetExists := operation.targets.Target(targetID)
		node, hasNode := target.Node()
		instances, hasInstances := target.Instances()

		if !targetExists {
			// this is strange
			logger.Warning("Internal target error, was told to use a target that doesn't exist")
			continue
		}

		nodeLogger := logger.MakeChild(targetID)
		status := []string{}

		if hasNode {
			status = append(status, operation.NodeStatus(nodeLogger, node)...)
		} else {
			status = append(status, "No node for target")
		}
		if hasInstances {
			status = append(status, operation.InstancesStatus(nodeLogger, instances)...)
		} else {
			status = append(status, "No instances for target")
		}

		nodeLogger.Message("[" + strings.Join(status, "][") + "]")
	}

	return true
}
예제 #22
0
파일: user.go 프로젝트: james-nesbitt/coach
func (tasks *InitTasks) Init_User_Run(logger log.Log, template string) bool {

	if template == "" {
		logger.Error("You have not provided a template name  $/> coach init user {template}")
		return false
	}

	templatePath, ok := tasks.conf.Path("user-templates")
	if !ok {
		logger.Error("COACH has no user template path for the current user")
		return false
	}
	sourcePath := path.Join(templatePath, template)

	if _, err := os.Stat(sourcePath); err != nil {
		logger.Error("Invalid template path suggested for new project init : [" + template + "] expected path [" + sourcePath + "] => " + err.Error())
		return false
	}

	logger.Message("Perfoming init operation from user template [" + template + "] : " + sourcePath)

	tasks.AddFileCopy(tasks.root, sourcePath)

	tasks.AddMessage("Copied coach template [" + template + "] to init project")
	tasks.AddFile(".coach/CREATEDFROM.md", `THIS PROJECT WAS CREATED FROM A User Template :`+template)

	return true
}
예제 #23
0
파일: git.go 프로젝트: james-nesbitt/coach
func (tasks *InitTasks) Init_Git_Run(logger log.Log, source string) bool {

	if source == "" {
		logger.Error("You have not provided a git target $/> coach init git https://github.com/aleksijohansson/docker-drupal-coach")
		return false
	}

	url := source
	path := tasks.root

	cmd := exec.Command("git", "clone", "--progress", url, path)
	cmd.Stdin = os.Stdin
	cmd.Stdout = logger
	cmd.Stderr = logger

	err := cmd.Start()

	if err != nil {
		logger.Error("Failed to clone the remote repository [" + url + "] => " + err.Error())
		return false
	}

	logger.Message("Clone remote repository to local project folder [" + url + "]")
	err = cmd.Wait()

	if err != nil {
		logger.Error("Failed to clone the remote repository [" + url + "] => " + err.Error())
		return false
	}

	tasks.AddMessage("Cloned remote repository [" + url + "] to local project folder")
	tasks.AddFile(".coach/CREATEDFROM.md", `THIS PROJECT WAS CREATED FROM GIT`)

	return true
}
예제 #24
0
func (clientFactory *FSouza_ClientFactory) Init(logger log.Log, project *conf.Project, settings ClientFactorySettings) bool {
	clientFactory.log = logger
	clientFactory.conf = project

	// make sure that the settings that were given, where the proper "FSouza_ClientFactory" type
	typedSettings := settings.Settings()
	switch asserted := typedSettings.(type) {
	case *FSouza_ClientFactorySettings:
		clientFactory.settings = *asserted
	default:
		logger.Error("Invalid settings type passed to Fsouza Factory")
		logger.Debug(log.VERBOSITY_DEBUG, "Settings passed:", asserted)
	}

	// if we haven't made an actual fsouza docker client, then do it now
	if clientFactory.client == nil {
		if client, pk := clientFactory.makeFsouzaClientWrapper(logger.MakeChild("fsouza")); pk {
			clientFactory.client = client
			return true
		} else {
			logger.Error("Failed to create actual FSouza Docker client from client factory configuration")
			return false
		}
	}
	return true
}
예제 #25
0
func (operation *BuildOperation) Run(logger log.Log) bool {
	logger.Info("Running operation: build")
	logger.Debug(log.VERBOSITY_DEBUG, "Run:Targets", operation.targets.TargetOrder())

	for _, targetID := range operation.targets.TargetOrder() {
		target, targetExists := operation.targets.Target(targetID)
		if !targetExists {
			// this is strange
			logger.Warning("Internal target error, was told to use a target that doesn't exist")
			continue
		}

		node, hasNode := target.Node()
		nodeLogger := logger.MakeChild(targetID)

		if !hasNode {
			nodeLogger.Info("No node [" + node.MachineName() + "]")
		} else if !node.Can("build") {
			nodeLogger.Info("Node doesn't build [" + node.MachineName() + "]")
		} else {
			nodeLogger.Message("Building node")
			node.Client().Build(nodeLogger, operation.force)
		}
	}

	return true
}
예제 #26
0
func (operation *InfoOperation) Run(logger log.Log) bool {
	logger.Message("RUNNING INFO OPERATION")

	logger.Debug(log.VERBOSITY_DEBUG, "Run:Targets", operation.targets.TargetOrder())
	for _, targetID := range operation.targets.TargetOrder() {
		target, targetExists := operation.targets.Target(targetID)
		node, hasNode := target.Node()
		_, hasInstances := target.Instances()

		if !targetExists {
			// this is strange
			logger.Warning("Internal target error, was told to use a target that doesn't exist")
			continue
		}

		nodeLogger := logger.MakeChild(targetID)

		if hasNode {
			nodeLogger.Message(targetID + " Information")
			node.Client().NodeInfo(nodeLogger)
		} else {
			nodeLogger.Message("No node [" + node.MachineName() + "]")
		}
		if hasInstances {
			node.Instances().Client().InstancesInfo(nodeLogger)
		} else {
			nodeLogger.Message("|-- No instances [" + node.MachineName() + "]")
		}
	}

	return true
}
예제 #27
0
func (operation *CreateOperation) Run(logger log.Log) bool {
	logger.Info("Running operation: create")
	logger.Debug(log.VERBOSITY_DEBUG, "Run:Targets", operation.targets.TargetOrder())

	for _, targetID := range operation.targets.TargetOrder() {
		target, targetExists := operation.targets.Target(targetID)
		if !targetExists {
			// this is strange
			logger.Warning("Internal target error, was told to use a target that doesn't exist")
			continue
		}

		node, hasNode := target.Node()
		instances, hasInstances := target.Instances()
		nodeLogger := logger.MakeChild(targetID)

		if !hasNode {
			nodeLogger.Warning("No node [" + node.MachineName() + "]")
		} else if !node.Can("create") {
			nodeLogger.Info("Node doesn't create [" + node.MachineName() + ":" + node.Type() + "]")
		} else if !hasInstances {
			nodeLogger.Info("No valid instances specified in target list [" + node.MachineName() + "]")
		} else {
			nodeLogger.Message("Creating instance containers")
			for _, id := range instances.InstancesOrder() {
				instance, _ := instances.Instance(id)
				instance.Client().Create(logger, []string{}, operation.force)
			}
		}
	}

	return true
}
예제 #28
0
파일: node.go 프로젝트: james-nesbitt/coach
// Post initialization preparation
func (node *BaseNode) Prepare(logger log.Log, nodes *Nodes) (success bool) {
	logger.Debug(log.VERBOSITY_DEBUG_WOAH, "Prepare: Base Node")
	success = true

	node.log = logger

	logger.Debug(log.VERBOSITY_DEBUG_WOAH, "Preparing Client", nil)
	success = success && node.client.Prepare(logger.MakeChild("client"), nodes, node)

	logger.Debug(log.VERBOSITY_DEBUG_WOAH, "Preparing Instances", nil)
	success = success && node.instances.Prepare(logger.MakeChild("instances"), node.client, nodes, node)

	return success
}
예제 #29
0
func Init_Generate(logger log.Log, handler string, path string, skip []string, sizeLimit int64, output io.Writer) bool {
	logger.Message("GENERATING INIT")

	var generator Generator
	switch handler {
	case "test":
		generator = Generator(&TestInitGenerator{logger: logger, output: output})
	case "yaml":
		generator = Generator(&YMLInitGenerator{logger: logger, output: output})
	default:
		logger.Error("Unknown init generator (handler) " + handler)
		return false
	}

	iterator := GenerateIterator{
		logger:    logger,
		output:    output,
		skip:      skip,
		sizeLimit: sizeLimit,
		generator: generator,
	}

	if iterator.Generate(path) {
		logger.Message("FINISHED GENERATING YML INIT")
		return true
	} else {
		logger.Error("ERROR OCCURRED GENERATING YML INIT")
		return false
	}
}
예제 #30
0
// Try to configure help by parsing yaml from a byte stream
func (help *Help) from_HelpYamlBytes(logger log.Log, project *conf.Project, yamlBytes []byte) bool {
	if project != nil {
		// token replace
		tokens := &project.Tokens
		yamlBytes = []byte(tokens.TokenReplace(string(yamlBytes)))
		logger.Debug(log.VERBOSITY_DEBUG_LOTS, "Tokenized Bytes", string(yamlBytes))
	}

	if err := yaml.Unmarshal(yamlBytes, help); err != nil {
		logger.Warning("YAML parsing error : " + err.Error())
		// logger.Debug(log.VERBOSITY_DEBUG, "YAML parsing error : " + err.Error(), string(yamlBytes))
		return false
	}
	return true
}