Example #1
0
// Password retrieves a password from stdin without echoing it.
func Password(prefix string) (string, error) {
	var err error
	line := ""

	term, err := NewTerminal()
	if err != nil {
		return "", err
	}
	defer term.Close()

	for line == "" {
		line, err = term.Password(prefix + ": ")
		if err != nil && err != io.EOF {
			se := errors.IsStackError(err)

			if se == nil || se.Err != io.EOF {
				return "", err
			}
		}

		if line == "" {
			log.Fprintln(os.Stderr, "red", prefix, errors.ErrEmpty)
		}
	}

	return line, nil
}
Example #2
0
// Basic gets input and if required tests to ensure input was given.
func Basic(prefix string, required bool) (string, error) {
	return Custom(prefix, func(input string) (string, bool) {
		if required && input == "" {
			log.Fprintln(os.Stderr, "red", prefix, errors.ErrEmpty)
			return "", false
		}

		return input, true
	})
}
Example #3
0
// getToken gets the login information for a developer and gets a new token.
func getToken(dev *db.Developer) error {
	var err error
	i := 0
	token := ""

	// Get email and password up to 5 times, then report the error.
	for token == "" && i < 5 {
		validEmail := false
		email := ""
		pass := ""

		for !validEmail {
			email, err = prompt.Basic("Email", true)
			if err != nil {
				return err
			}

			_, err = mail.ParseAddress(email)
			if err == nil {
				validEmail = true
			} else {
				log.Println("yellow", "Try again! Valid email address required.")
			}
		}

		pass, err = prompt.Password("Password")
		if err != nil {
			return err
		}
		log.Debug("Collected email", email, "pass", pass)

		token, err = broome.GetTokenByLogin(email, pass)
		if err != nil {
			if i < 4 {
				log.Fprintln(os.Stderr, "red", errors.Newf(errors.ErrLoginRetryTmpl, err))
			}
			i++
		}
	}

	if err != nil {
		if err == errors.ErrInvalidLogin {
			err = errors.ErrTooManyLogins
		}

		return err
	}

	log.Debug("Got token", token)
	dev.Token = token
	return dev.Save()
}
Example #4
0
func main() {
	if env == "" {
		env = "production"
	}

	// Remove any previous executables, ignore errors as it isn't essential.
	exec, _ := osext.Executable()
	if exec != "" {
		os.Remove(filepath.Join(filepath.Dir(exec), ".old_bowery"+filepath.Ext(exec)))
	}

	// Set up error and analytics reporting.
	keen := &keen.Client{
		WriteKey:  "8bbe0d9425a22a6c31e6da9ae3012c738ee21000b533c351a419bb0e3d08431456359d1bea654a39c2065df0b1df997ecde7e3cf49a9be0cd44341b15c1ff5523f13d26d8060373390f47bcc6a33b80e69e2b2c1101cde4ddb3d20b16a53a439a98043919e809c09c30e4856dedc963f",
		ProjectID: "52c08d6736bf5a4a4b000005",
	}
	rollbar := &rollbar.Client{
		Token: "a7c4e78074034f04b1882af596657295",
		Env:   env,
	}

	// Parse flags and get arguments.
	flag.Usage = func() {
		Cmds["help"].Run(keen, rollbar)
	}

	flag.Parse()
	args := flag.Args()
	command := "help"

	if len(args) >= 1 {
		command = args[0]
		args = args[1:]
	}

	// Run command, and handle invalid commands.
	cmd, ok := Cmds[command]
	if !ok {
		keen.AddEvent("invalid command", map[string]string{"command": command})

		log.Fprintln(os.Stderr, "red", errors.ErrInvalidCommand, command)
		os.Exit(Cmds["help"].Run(keen, rollbar))
	}

	cmd.Force = force
	os.Exit(cmd.Run(keen, rollbar, args...))
}
Example #5
0
// Ask gets input and checks if it's truthy or not, and returns that
// in a boolean fashion.
func Ask(question string) (bool, error) {
	line, err := Custom(question+"?(y/n)", func(input string) (string, bool) {
		if input == "" {
			log.Fprintln(os.Stderr, "red", "Answer", errors.ErrEmpty)
			return "", false
		}
		input = strings.ToLower(input)

		if input == "y" || input == "yes" {
			return "yes", true
		}

		return "", true
	})

	ok := false
	if line != "" {
		ok = true
	}

	return ok, err
}
Example #6
0
func saveRun(keen *keen.Client, rollbar *rollbar.Client, args ...string) int {
	if len(args) <= 0 {
		fmt.Fprintln(os.Stderr,
			"Usage: bowery "+Cmds["save"].Usage, "\n\n"+Cmds["save"].Short)
		return 2
	}

	dev, err := getDeveloper()
	if err != nil {
		rollbar.Report(err)
		return 1
	}

	state, err := db.GetState()
	if err != nil {
		rollbar.Report(err)
		return 1
	}

	// Create slices of service names, and find the requested service.
	var service *schemas.Service
	services := make([]string, len(state.App.Services))
	for i, v := range state.App.Services {
		services[i] = v.Name
		if args[0] == v.Name {
			service = v
			break
		}
	}

	// Handle no service found.
	if service == nil {
		log.Fprintln(os.Stderr, "red", errors.ErrInvalidService, args[0])
		log.Println("yellow", "Valid services:", strings.Join(services, ", "))
		return 1
	}
	log.Debug("Found service", service.Name, "public addr:", service.PublicAddr)

	// Get image name
	log.Println("yellow", "What would you like to call this image?")
	imageName, err := prompt.Basic("Image Name", true)
	if err != nil {
		rollbar.Report(err)
		return 1
	}
	log.Debug("Collected Image Name", imageName)

	imageDesc, err := prompt.Basic("Description", true)
	if err != nil {
		rollbar.Report(err)
		return 1
	}
	log.Debug("Collected Description", imageDesc)

	log.Println("yellow", "A new image is being created and saved to our registry...")
	log.Println("yellow", "This may take a couple minutes.")

	err = api.SaveService(state, dev, service.Name, service.PublicAddr, imageName, imageDesc)
	if err != nil {
		errmsg := err.Error()
		if errmsg == imageName+" is an invalid service name" ||
			errmsg == "Image already exists" {
			log.Println("yellow", err)
		} else {
			rollbar.Report(err)
		}

		return 1
	}

	log.Println("yellow", imageName+" successfully created.")

	keen.AddEvent("bowery save", map[string]string{
		"serviceName": service.Name,
		"imageName":   imageName,
		"appId":       state.App.ID,
	})
	return 0
}
Example #7
0
func restartRun(keen *keen.Client, rollbar *rollbar.Client, args ...string) int {
	if len(args) <= 0 {
		fmt.Fprintln(os.Stderr,
			"Usage: bowery "+Cmds["restart"].Usage, "\n\n"+Cmds["restart"].Short)
		return 2
	}

	dev, err := getDeveloper()
	if err != nil {
		rollbar.Report(err)
		return 1
	}

	state, err := db.GetState()
	if err != nil {
		rollbar.Report(err)
		return 1
	}

	// Create slices of service names, and find the requested service.
	var service *schemas.Service
	services := make([]string, len(state.App.Services))
	serviceIdx := -1
	for i, v := range state.App.Services {
		services[i] = v.Name
		if args[0] == v.Name {
			service = v
			serviceIdx = i
			break
		}
	}

	// Handle no service found.
	if service == nil {
		log.Fprintln(os.Stderr, "red", errors.ErrInvalidService, args[0])
		log.Println("yellow", "Valid services:", strings.Join(services, ", "))
		return 1
	}
	log.Debug("Found service", service.Name)

	newService, err := api.RestartService(service.DockerID, dev.Token)
	if err != nil {
		rollbar.Report(err)
		return 1
	}

	if newService != nil {
		state.App.Services[serviceIdx] = newService
		service = newService

		err = state.Save()
		if err != nil {
			rollbar.Report(err)
			return 1
		}
	}

	keen.AddEvent("bowery restart", map[string]string{
		"name":  service.Name,
		"appId": state.App.ID,
	})
	return 0
}