Example #1
0
func cleanRun(keen *keen.Client, rollbar *rollbar.Client, args ...string) int {
	db.GetState() // Do this to ensure we're at the root of the app.

	contents, _ := ioutil.ReadFile(filepath.Join(".bowery", "state"))
	if len(contents) > 0 {
		keen.AddEvent("bowery clean", map[string]string{
			"contents": string(contents),
		})
	}

	err := os.RemoveAll(".bowery")
	if err != nil {
		rollbar.Report(err)
		return 1
	}

	return 0
}
Example #2
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 #3
0
// Upload sends an upload request to a satellite endpoint, including
// a tar upload file if given.
func Upload(url, serviceName string, file *os.File) error {
	var body bytes.Buffer
	writer := multipart.NewWriter(&body)

	// Write file to multipart body if given.
	if file != nil {
		part, err := writer.CreateFormFile("file", "upload")
		if err != nil {
			return errors.NewStackError(err)
		}

		_, err = io.Copy(part, file)
		if err != nil {
			return err
		}
	}

	// Get current app and add fields for init, build, test, and start.
	state, err := db.GetState()
	if err != nil {
		return err
	}

	service := state.Config[serviceName]
	if service != nil {
		err = writer.WriteField("init", service.Init)
		if err == nil {
			err = writer.WriteField("build", service.Build)
		}
		if err == nil {
			err = writer.WriteField("test", service.Test)
		}
		if err == nil {
			err = writer.WriteField("start", service.Start)
		}
		if err == nil {
			err = writer.WriteField("path", service.Path)
		}
		if err == nil && service.Env != nil {
			envData, err := json.Marshal(service.Env)
			if err != nil {
				return err
			}
			err = writer.WriteField("env", string(envData))
		}
	}
	if err == nil {
		err = writer.Close()
	}
	if err != nil {
		return err
	}

	res, err := http.Post("http://"+url, writer.FormDataContentType(), &body)
	if err != nil {
		if responses.IsRefusedConn(err) {
			err = errors.ErrSyncFailed
		}

		return errors.NewStackError(err)
	}
	defer res.Body.Close()

	// Decode json response.
	uploadRes := new(responses.Res)
	decoder := json.NewDecoder(res.Body)
	err = decoder.Decode(uploadRes)
	if err != nil {
		return errors.NewStackError(err)
	}

	// Created, so no error.
	if uploadRes.Status == "created" {
		return nil
	}

	return errors.NewStackError(uploadRes)
}
Example #4
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
}
Example #5
0
// Update updates the given name with the status and path.
func Update(url, serviceName, fullPath, name, status string) error {
	var body bytes.Buffer

	// Create writer, and write form fields.
	writer := multipart.NewWriter(&body)
	err := writer.WriteField("type", status)
	if err == nil {
		err = writer.WriteField("path", path.Join(strings.Split(name, string(filepath.Separator))...))
	}
	if err != nil {
		return errors.NewStackError(err)
	}

	// Attach file if update or create.
	if status == "update" || status == "create" {
		file, err := os.Open(fullPath)
		if err != nil {
			return err
		}
		defer file.Close()

		stat, err := file.Stat()
		if err != nil {
			return err
		}

		// Add file mode to write with.
		err = writer.WriteField("mode", strconv.FormatUint(uint64(stat.Mode().Perm()), 10))
		if err != nil {
			return errors.NewStackError(err)
		}

		part, err := writer.CreateFormFile("file", "upload")
		if err != nil {
			return errors.NewStackError(err)
		}

		_, err = io.Copy(part, file)
		if err != nil {
			return err
		}
	}

	// Get current app and add fields for init, build, test, and start.
	state, err := db.GetState()
	if err != nil {
		return err
	}

	if service := state.Config[serviceName]; service != nil {
		writer.WriteField("init", service.Init)
		writer.WriteField("build", service.Build)
		writer.WriteField("test", service.Test)
		writer.WriteField("start", service.Start)

		if service.Env != nil {
			envData, err := json.Marshal(service.Env)
			if err != nil {
				return err
			}
			err = writer.WriteField("env", string(envData))
		}
	}

	if err = writer.Close(); err != nil {
		return err
	}

	req, err := http.NewRequest("PUT", "http://"+url, &body)
	if err != nil {
		return errors.NewStackError(err)
	}
	req.Header.Set("Content-Type", writer.FormDataContentType())

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		if responses.IsRefusedConn(err) {
			err = errors.ErrSyncFailed
		}

		return errors.NewStackError(err)
	}
	defer res.Body.Close()

	// Decode json response.
	uploadRes := new(responses.Res)
	decoder := json.NewDecoder(res.Body)
	err = decoder.Decode(uploadRes)
	if err != nil {
		return errors.NewStackError(err)
	}

	// Created, so no error.
	if uploadRes.Status == "updated" {
		return nil
	}

	return errors.NewStackError(uploadRes)
}