Example #1
0
func List() error {
	c := config.ScalingoClient()
	apps, err := c.AppsList()
	if err != nil {
		return errgo.Mask(err, errgo.Any)
	}

	if len(apps) == 0 {
		fmt.Println(io.Indent("\nYou haven't created any app yet, create your first application using:\n→ scalingo create <app_name>\n", 2))
		return nil
	}

	t := tablewriter.NewWriter(os.Stdout)
	t.SetHeader([]string{"Name", "Role", "Owner"})

	for _, app := range apps {
		if app.Owner.Email == config.AuthenticatedUser.Email {
			t.Append([]string{app.Name, "owner", "-"})
		} else {
			t.Append([]string{app.Name, "collaborator", fmt.Sprintf("%s <%s>", app.Owner.Username, app.Owner.Email)})
		}
	}
	t.Render()

	return nil
}
Example #2
0
func Add(name string, path string) error {
	stat, err := os.Stat(path)
	if err != nil {
		return errgo.Mask(err)
	}
	if stat.Mode().IsDir() {
		return errgo.Newf("%s: is a directory", path)
	}
	if stat.Size() > 10*1024*1024 {
		return errgo.Newf("%s: is too large (%v bytes)", stat.Size())
	}

	keyContent, err := ioutil.ReadFile(path)
	if err != nil {
		return errgo.Mask(err)
	}

	c := config.ScalingoClient()
	_, err = c.KeysAdd(name, string(keyContent))
	if err != nil {
		return errgo.Mask(err)
	}

	fmt.Printf("Key '%s' has been added.\n", name)
	return nil
}
Example #3
0
func DbTunnelAutoComplete(c *cli.Context) error {
	appName := CurrentAppCompletion(c)
	if appName == "" {
		return nil
	}

	lastArg := ""
	if len(os.Args) > 2 {
		lastArg = os.Args[len(os.Args)-2]
	}

	if !strings.HasPrefix(lastArg, "-") {
		client := config.ScalingoClient()
		variables, err := client.VariablesList(appName)
		if err == nil {

			for _, v := range variables {
				if matched, err := regexp.Match("SCALINGO_.*_URL", []byte(v.Name)); matched && err == nil {
					fmt.Println(v.Name)
				}
			}
		}
	}

	return nil
}
Example #4
0
func Add(app string, params []string) error {
	var variables scalingo.Variables
	for _, param := range params {
		if err := isEnvEditValid(param); err != nil {
			return errgo.Newf("'%s' is invalid: %s", param, err)
		}

		name, value := parseVariable(param)
		variables = append(variables, &scalingo.Variable{
			Name:  name,
			Value: value,
		})
	}

	c := config.ScalingoClient()
	_, _, err := c.VariableMultipleSet(app, variables)
	if err != nil {
		return errgo.Mask(err, errgo.Any)
	}

	for _, variable := range variables {
		fmt.Printf("%s has been set to '%s'.\n", variable.Name, variable.Value)
	}

	return nil
}
Example #5
0
func Delete(app string, varNames []string) error {
	c := config.ScalingoClient()
	vars, err := c.VariablesList(app)

	if err != nil {
		return errgo.Mask(err, errgo.Any)
	}

	var varsToUnset scalingo.Variables

	for _, varName := range varNames {
		v, ok := vars.Contains(varName)
		if !ok {
			return errgo.Newf("%s variable does not exist", varName)
		}
		varsToUnset = append(varsToUnset, v)
	}

	for _, v := range varsToUnset {
		err := c.VariableUnset(app, v.ID)
		if err != nil {
			return errgo.Mask(err, errgo.Any)
		}
		fmt.Printf("%s has been unset.\n", v.Name)
	}
	return nil
}
Example #6
0
func AddonsAddAutoComplete(c *cli.Context) error {
	client := config.ScalingoClient()
	resources, err := client.AddonProvidersList()
	if len(os.Args) > 1 && err == nil {
		lastArg := os.Args[len(os.Args)-2]
		isAddonNameSet := false

		for _, resource := range resources {
			if lastArg == resource.ID {
				isAddonNameSet = true
				break
			}
		}

		if isAddonNameSet {
			plans, err := client.AddonProviderPlansList(lastArg)

			if err == nil {
				for _, plan := range plans {
					fmt.Println(plan.Name)
				}
			}
		} else {

			for _, resource := range resources {
				fmt.Println(resource.ID)
			}
		}
	}

	return nil
}
Example #7
0
func Add(app, email string) error {
	c := config.ScalingoClient()
	collaborator, err := c.CollaboratorAdd(app, email)
	if err != nil {
		return errgo.Mask(err, errgo.Any)
	}

	io.Status(collaborator.Email, "has been invited to collaborate to", app)
	return nil
}
Example #8
0
func KeysRemoveAutoComplete(c *cli.Context) error {
	client := config.ScalingoClient()
	keys, err := client.KeysList()
	if err == nil {
		for _, key := range keys {
			fmt.Println(key.Name)
		}
	}

	return nil
}
Example #9
0
func Display(app string) error {
	c := config.ScalingoClient()
	vars, err := c.VariablesList(app)
	if err != nil {
		return errgo.Mask(err, errgo.Any)
	}

	for _, v := range vars {
		fmt.Printf("%s=%s\n", v.Name, v.Value)
	}
	return nil
}
Example #10
0
func keyByName(name string) (*scalingo.Key, error) {
	c := config.ScalingoClient()
	keys, err := c.KeysList()
	if err != nil {
		return nil, errgo.Mask(err)
	}
	for _, k := range keys {
		if k.Name == name {
			return &k, nil
		}
	}
	return nil, errgo.New("no such key")
}
Example #11
0
func getFromEmail(app, email string) (scalingo.Collaborator, error) {
	c := config.ScalingoClient()
	collaborators, err := c.CollaboratorsList(app)
	if err != nil {
		return scalingo.Collaborator{}, errgo.Mask(err, errgo.Any)
	}
	for _, collaborator := range collaborators {
		if collaborator.Email == email {
			return collaborator, nil
		}
	}
	return scalingo.Collaborator{}, notFound
}
Example #12
0
func handleOperation(app string, res *http.Response) error {
	opURL, err := url.Parse(res.Header.Get("Location"))
	if err != nil {
		return errgo.Mask(err)
	}

	var op *scalingo.Operation

	opID := filepath.Base(opURL.Path)
	done := make(chan struct{})
	errs := make(chan error)
	defer close(done)
	defer close(errs)

	go func() {
		c := config.ScalingoClient()
		for {
			op, err = c.OperationsShow(app, opID)
			if err != nil {
				errs <- err
				break
			}

			if op.Status == "done" || op.Status == "error" {
				done <- struct{}{}
				break
			}
			time.Sleep(1 * time.Second)
		}
	}()

	fmt.Print("Status:  ")
	spinner := io.NewSpinner(os.Stderr)
	go spinner.Start()
	defer spinner.Stop()

	for {
		select {
		case err := <-errs:
			return errgo.Mask(err)
		case <-done:
			if op.Status == "done" {
				fmt.Printf("\bDone in %.3f seconds\n", op.ElapsedDuration())
				return nil
			} else if op.Status == "error" {
				fmt.Printf("\bOperation '%s' failed, an error occured: %v\n", op.Type, op.Error)
				return nil
			}
		}
	}
}
Example #13
0
func findDomain(app string, domain string) (scalingo.Domain, error) {
	c := config.ScalingoClient()
	domains, err := c.DomainsList(app)
	if err != nil {
		return scalingo.Domain{}, errgo.Mask(err)
	}

	for _, d := range domains {
		if d.Name == domain {
			return d, nil
		}
	}
	return scalingo.Domain{}, errgo.New("There is no such domain, please ensure you've added it correctly.\nhttps://my.scalingo.com/apps/" + app + "/domains")
}
Example #14
0
func DisableSSL(app string, domain string) error {
	d, err := findDomain(app, domain)
	if err != nil {
		return errgo.Mask(err)
	}

	c := config.ScalingoClient()
	_, err = c.DomainsUpdate(app, d.ID, "", "")
	if err != nil {
		return errgo.Mask(err)
	}
	io.Status("SSL of " + domain + " has been disabled.")
	return nil
}
Example #15
0
func Remove(name string) error {
	k, err := keyByName(name)
	if err != nil {
		return errgo.Mask(err)
	}

	c := config.ScalingoClient()
	err = c.KeysDelete(k.ID)
	if err != nil {
		return errgo.Mask(err)
	}

	fmt.Printf("Key '%s' has been deleted.\n", name)
	return nil
}
Example #16
0
func Remove(app string, domain string) error {
	d, err := findDomain(app, domain)
	if err != nil {
		return errgo.Mask(err)
	}

	c := config.ScalingoClient()
	err = c.DomainsRemove(app, d.ID)
	if err != nil {
		return errgo.Mask(err)
	}

	io.Status("The domain", d.Name, "has been deleted")
	return nil
}
Example #17
0
func DeploymentsAutoComplete(c *cli.Context) error {
	client := config.ScalingoClient()
	currentApp := appdetect.CurrentApp(c)

	deployments, err := client.DeploymentList(currentApp)
	if err != nil {
		return errgo.Mask(err, errgo.Any)
	}

	for _, deployment := range deployments {
		fmt.Println(deployment.ID)
	}

	return nil
}
Example #18
0
func List(app string) error {
	c := config.ScalingoClient()
	collaborators, err := c.CollaboratorsList(app)
	if err != nil {
		return errgo.Mask(err, errgo.Any)
	}

	t := tablewriter.NewWriter(os.Stdout)
	t.SetHeader([]string{"Email", "Username", "Status"})

	for _, collaborator := range collaborators {
		t.Append([]string{collaborator.Email, collaborator.Username, collaborator.Status})
	}
	t.Render()
	return nil
}
Example #19
0
func ScaleAutoComplete(c *cli.Context) error {
	appName := CurrentAppCompletion(c)
	if appName == "" {
		return nil
	}

	client := config.ScalingoClient()
	processes, err := client.AppsPs(appName)
	if err != nil {
		return errgo.Mask(err)
	}
	for _, ct := range processes {
		fmt.Println(fmt.Sprintf("%s:%d:%s", ct.Name, ct.Amount, ct.Size))
	}

	return nil
}
Example #20
0
func RestartAutoComplete(c *cli.Context) error {
	appName := CurrentAppCompletion(c)
	if appName == "" {
		return nil
	}

	client := config.ScalingoClient()
	processes, err := client.AppsPs(appName)
	if err != nil {
		return errgo.Mask(err)
	}
	for _, ct := range processes {
		fmt.Println(ct.Name)
	}

	return nil
}
Example #21
0
func EnvUnsetAutoComplete(c *cli.Context) error {
	appName := CurrentAppCompletion(c)
	if appName == "" {
		return nil
	}

	client := config.ScalingoClient()
	variables, err := client.VariablesList(appName)
	if err == nil {

		for _, v := range variables {
			fmt.Println(v.Name)
		}
	}

	return nil
}
Example #22
0
func AddonsRemoveAutoComplete(c *cli.Context) error {
	appName := CurrentAppCompletion(c)
	if appName == "" {
		return nil
	}

	client := config.ScalingoClient()
	resources, err := client.AddonsList(appName)
	if err == nil {

		for _, resource := range resources {
			fmt.Println(resource.ResourceID)
		}
	}

	return nil
}
Example #23
0
func DomainsRemoveAutoComplete(c *cli.Context) error {
	appName := CurrentAppCompletion(c)
	if appName == "" {
		return nil
	}

	client := config.ScalingoClient()
	domains, err := client.DomainsList(appName)
	if err == nil {

		for _, domain := range domains {
			fmt.Println(domain.Name)
		}
	}

	return nil
}
Example #24
0
func Remove(app, email string) error {
	collaborator, err := getFromEmail(app, email)
	if err != nil {
		if err == notFound {
			io.Error(email + " is not a collaborator of " + app + ".")
			return nil
		} else {
			return errgo.Mask(err, errgo.Any)
		}
	}

	c := config.ScalingoClient()
	err = c.CollaboratorRemove(app, collaborator.ID)
	if err != nil {
		return errgo.Mask(err, errgo.Any)
	}

	io.Status(email, "has been removed from the collaborators of", app)
	return nil
}
Example #25
0
func EnableSSL(app, domain, certPath, keyPath string) error {
	d, err := findDomain(app, domain)
	if err != nil {
		return errgo.Mask(err)
	}

	certContent, keyContent, err := validateSSL(certPath, keyPath)
	if err != nil {
		return errgo.Mask(err)
	}

	c := config.ScalingoClient()
	d, err = c.DomainsUpdate(app, d.ID, certContent, keyContent)
	if err != nil {
		return errgo.Mask(err)
	}

	io.Status("The certificate and key have been installed for " + d.Name + " (Validity: " + d.Validity.UTC().String() + ")")
	return nil
}
Example #26
0
func Provision(app, webHookURL string) error {
	if app == "" {
		return errgo.New("no app defined")
	} else if webHookURL == "" {
		return errgo.New("no url defined")
	}

	c := config.ScalingoClient()
	params, err := c.NotificationProvision(app, webHookURL)
	if err != nil {
		return errgo.Mask(err, errgo.Any)
	}

	io.Status("Notifications to", webHookURL, "have been provisionned")
	if len(params.Variables) > 0 {
		io.Info("Modified variables:", params.Variables)
	}
	if len(params.Message) > 0 {
		io.Info("Message from notification provider:", params.Message)
	}
	return nil
}
Example #27
0
func updateTtySize(url string) error {
	cols, err := term.Cols()
	if err != nil {
		return errgo.Mask(err, errgo.Any)
	}
	lines, err := term.Lines()
	if err != nil {
		return errgo.Mask(err, errgo.Any)
	}

	params := UpdateTtyParams{
		fmt.Sprintf("%d", cols),
		fmt.Sprintf("%d", lines),
	}
	paramsJson, err := json.Marshal(&params)
	if err != nil {
		return errgo.Mask(err, errgo.Any)
	}

	req, err := http.NewRequest("PUT", url, bytes.NewReader(paramsJson))
	if err != nil {
		return errgo.Mask(err, errgo.Any)
	}
	req.SetBasicAuth("", config.ScalingoClient().APIToken)
	debug.Printf("Updating TTY Size: PUT %v %+v", url, params)

	res, err := httpclient.Do(req)
	if err != nil {
		return errgo.Mask(err, errgo.Any)
	}
	defer res.Body.Close()
	if res.StatusCode != 200 {
		return errgo.Newf("Invalid error code from run server: %s", res.Status)
	}

	return nil
}
Example #28
0
func AddonsUpgradeAutoComplete(c *cli.Context) error {
	appName := CurrentAppCompletion(c)
	addonName := ""
	if appName == "" {
		return nil
	}

	client := config.ScalingoClient()
	resources, err := client.AddonsList(appName)
	if len(os.Args) > 1 && err == nil {

		lastArg := os.Args[len(os.Args)-2]
		isAddonIDSet := false
		for _, resource := range resources {
			if lastArg == resource.ResourceID {
				isAddonIDSet = true
				addonName = resource.AddonProvider.ID
				break
			}
		}

		if isAddonIDSet && addonName != "" {
			plans, err := client.AddonProviderPlansList(addonName)
			if err == nil {
				for _, plan := range plans {
					fmt.Println(plan.Name)
				}
			}
		} else {
			for _, resource := range resources {
				fmt.Println(resource.ResourceID)
			}
		}
	}

	return nil
}
Example #29
0
func CollaboratorsAddAutoComplete(c *cli.Context) error {
	var err error
	appName := CurrentAppCompletion(c)
	if appName == "" {
		return nil
	}

	apps, err := appsList()
	if err != nil {
		debug.Println("fail to get apps list:", err)
		return nil
	}

	client := config.ScalingoClient()
	currentAppCollaborators, err := client.CollaboratorsList(appName)
	if err != nil {
		return nil
	}

	var apiError error = nil
	ch := make(chan string)
	var wg sync.WaitGroup
	wg.Add(len(apps))
	for _, app := range apps {
		go func(app *scalingo.App) {
			defer wg.Done()
			appCollaborators, erro := client.CollaboratorsList(app.Name)
			if erro != nil {
				config.C.Logger.Println(erro.Error())
				apiError = erro
				return
			}
			for _, col := range appCollaborators {
				ch <- col.Email
			}
		}(app)
	}

	setEmails := make(map[string]bool)
	go func() {
		for content := range ch {
			setEmails[content] = true
		}
	}()
	wg.Wait()
	close(ch)

	if apiError != nil {
		return nil
	}

	for email, _ := range setEmails {
		isAlreadyCollaborator := false
		for _, currentAppCol := range currentAppCollaborators {
			if currentAppCol.Email == email {
				isAlreadyCollaborator = true
			}
		}
		if !isAlreadyCollaborator {
			fmt.Println(email)
		}
	}
	return nil
}
Example #30
0
func Run(opts RunOpts) error {
	c := config.ScalingoClient()

	firstReadDone := make(chan struct{})
	ctx := &runContext{
		waitingTextOutputWriter: os.Stderr,
		stdinCopyFunc:           stdio.Copy,
		stdoutCopyFunc:          io.CopyWithFirstReadChan(firstReadDone),
	}
	if opts.Type != "" {
		processes, err := c.AppsPs(opts.App)
		if err != nil {
			return errgo.Mask(err)
		}
		for _, p := range processes {
			if p.Name == opts.Type {
				opts.Cmd = strings.Split(p.Command, " ")
			}
		}
		if strings.Join(opts.Cmd, "") == "" {
			return errgo.New("no such type")
		}
	}

	if opts.CmdEnv == nil {
		opts.CmdEnv = []string{}
	}
	if opts.Files == nil {
		opts.Files = []string{}
	}
	if opts.Silent {
		ctx.waitingTextOutputWriter = new(bytes.Buffer)
	}
	if opts.StdinCopyFunc != nil {
		ctx.stdinCopyFunc = opts.StdinCopyFunc
	}
	if opts.StdoutCopyFunc != nil {
		ctx.stdoutCopyFunc = opts.StdoutCopyFunc
	}

	env, err := ctx.buildEnv(opts.CmdEnv)
	if err != nil {
		return errgo.Mask(err, errgo.Any)
	}

	err = ctx.validateFiles(opts.Files)
	if err != nil {
		return errgo.Mask(err, errgo.Any)
	}

	res, err := c.Run(opts.App, opts.Cmd, env)
	if err != nil {
		return errgo.Mask(err, errgo.Any)
	}
	runStruct := make(map[string]interface{})
	scalingo.ParseJSON(res, &runStruct)
	debug.Printf("%+v\n", runStruct)

	if res.StatusCode == http.StatusNotFound {
		return errgo.Newf("application %s not found", opts.App)
	}

	var ok bool
	ctx.attachURL, ok = runStruct["attach_url"].(string)
	if !ok {
		return errgo.New("unexpected answer from server")
	}

	debug.Println("Run Service URL is", ctx.attachURL)

	if len(opts.Files) > 0 {
		err := ctx.uploadFiles(ctx.attachURL+"/files", opts.Files)
		if err != nil {
			return err
		}
	}

	fmt.Fprintf(ctx.waitingTextOutputWriter, "-----> Connecting to container [%v-%v]...  ",
		runStruct["container"].(map[string]interface{})["type"],
		runStruct["container"].(map[string]interface{})["type_index"],
	)

	attachSpinner := io.NewSpinner(ctx.waitingTextOutputWriter)
	attachSpinner.PostHook = func() {
		var displayCmd string
		if opts.DisplayCmd != "" {
			displayCmd = opts.DisplayCmd
		} else {
			displayCmd = strings.Join(opts.Cmd, " ")
		}
		fmt.Fprintf(ctx.waitingTextOutputWriter, "\n-----> Process '%v' is starting...  ", displayCmd)
	}
	go attachSpinner.Start()

	res, socket, err := ctx.connectToRunServer()
	if err != nil {
		return errgo.Mask(err, errgo.Any)
	}
	if res.StatusCode != http.StatusOK {
		return errgo.Newf("Fail to attach: %s", res.Status)
	}

	if term.IsATTY(os.Stdin) {
		if err := term.MakeRaw(os.Stdin); err != nil {
			return errgo.Mask(err, errgo.Any)
		}
	}

	stopSignalsMonitoring := make(chan bool)
	defer close(stopSignalsMonitoring)

	go func() {
		signals.CatchQuitSignals = false
		signals := run.NotifiedSignals()
		defer close(signals)

		go run.NofityTermSizeUpdate(signals)
		for {
			select {
			case s := <-signals:
				run.HandleSignal(s, socket, ctx.attachURL)
			case <-stopSignalsMonitoring:
				signal.Stop(signals)
				return
			}
		}
	}()

	attachSpinner.Stop()
	startSpinner := io.NewSpinnerWithStopChan(ctx.waitingTextOutputWriter, firstReadDone)
	startSpinner.PostHook = func() {
		fmt.Fprintf(ctx.waitingTextOutputWriter, "\n\n")
	}
	go startSpinner.Start()

	go func() {
		_, err := ctx.stdinCopyFunc(socket, os.Stdin)
		if err != nil {
			debug.Println("error after reading stdin", err)
		} else {
			// Send EOT when stdin returns
			// 'scalingo run < file'
			socket.Write([]byte("\x04"))
		}
	}()
	_, err = ctx.stdoutCopyFunc(os.Stdout, socket)

	stopSignalsMonitoring <- true

	if term.IsATTY(os.Stdin) {
		if err := term.Restore(os.Stdin); err != nil {
			return errgo.Mask(err, errgo.Any)
		}
	}

	exitCode, err := ctx.exitCode()
	if err != nil {
		return errgo.Mask(err, errgo.Any)
	}

	os.Exit(exitCode)
	return nil
}