Example #1
0
// Status prints out an environment healthcheck. The status of the environment
// and every service in the environment is printed out.
func Status(settings *models.Settings) {
	helpers.SignIn(settings)
	env := helpers.RetrieveEnvironment("pod", settings)
	fmt.Printf("%s (environment ID = %s):\n", env.Data.Name, env.ID)
	for _, service := range *env.Data.Services {
		if service.Type != "utility" {
			if service.Type == "code" {
				switch service.Size.(type) {
				case string:
					printLegacySizing(&service)
				default:
					printNewSizing(&service)
				}
			} else {
				switch service.Size.(type) {
				case string:
					sizeString := service.Size.(string)
					defer fmt.Printf("\t%s (size = %s, image = %s, status = %s) ID: %s\n", service.Label, sizeString, service.Name, service.DeployStatus, service.ID)
				default:
					serviceSize := service.Size.(map[string]interface{})
					defer fmt.Printf("\t%s (ram = %.0f, storage = %.0f, behavior = %s, type = %s, cpu = %.0f, image = %s, status = %s) ID: %s\n", service.Label, serviceSize["ram"], serviceSize["storage"], serviceSize["behavior"], serviceSize["type"], serviceSize["cpu"], service.Name, service.DeployStatus, service.ID)
				}
			}
		}
	}
}
Example #2
0
// Import imports data into a database service. The import is accomplished
// by encrypting the file locally, requesting a location that it can be uploaded
// to, then uploads the file. Once uploaded an automated service processes the
// file and acts according to the given parameters.
//
// The type of file that should be imported depends on the database. For
// PostgreSQL and MySQL, this should be a single `.sql` file. For Mongo, this
// should be a single tar'ed, gzipped archive (`.tar.gz`) of the database dump
// that you want to import.
func Import(databaseLabel string, filePath string, mongoCollection string, mongoDatabase string, wipeFirst bool, settings *models.Settings) {
	helpers.SignIn(settings)
	if _, err := os.Stat(filePath); os.IsNotExist(err) {
		fmt.Printf("A file does not exist at path '%s'\n", filePath)
		os.Exit(1)
	}
	service := helpers.RetrieveServiceByLabel(databaseLabel, settings)
	if service == nil {
		fmt.Printf("Could not find a service with the label \"%s\"\n", databaseLabel)
		os.Exit(1)
	}
	env := helpers.RetrieveEnvironment("spec", settings)
	pod := helpers.RetrievePodMetadata(env.PodID, settings)
	fmt.Printf("Importing '%s' into %s (ID = %s)\n", filePath, databaseLabel, service.ID)
	key := make([]byte, 32)
	iv := make([]byte, aes.BlockSize)
	rand.Read(key)
	rand.Read(iv)
	fmt.Println("Encrypting...")
	encrFilePath := helpers.EncryptFile(filePath, key, iv, pod.ImportRequiresLength)
	defer os.Remove(encrFilePath)
	options := map[string]string{}
	if mongoCollection != "" {
		options["mongoCollection"] = mongoCollection
	}
	if mongoDatabase != "" {
		options["mongoDatabase"] = mongoDatabase
	}
	fmt.Println("Uploading...")
	tempURL := helpers.RetrieveTempUploadURL(service.ID, settings)

	task := helpers.InitiateImport(tempURL.URL, encrFilePath, string(helpers.Base64Encode(helpers.Hex(key))), string(helpers.Base64Encode(helpers.Hex(iv))), options, wipeFirst, service.ID, settings)
	fmt.Printf("Processing import... (task ID = %s)\n", task.ID)

	ch := make(chan string, 1)
	go helpers.PollTaskStatus(task.ID, ch, settings)
	status := <-ch
	task.Status = status
	fmt.Printf("\nImport complete (end status = '%s')\n", task.Status)
	helpers.DumpLogs(service, task, "restore", settings)
	if task.Status != "finished" {
		os.Exit(1)
	}
}
Example #3
0
// Logs is a way to stream logs from Kibana to your local terminal. This is
// useful because Kibana is hard to look at because it splits every single
// log statement into a separate block that spans multiple lines so it's
// not very cohesive. This is intended to be similar to the `heroku logs`
// command.
func Logs(queryString string, tail bool, hours int, minutes int, seconds int, settings *models.Settings) {
	if settings.Username == "" || settings.Password == "" {
		// sometimes this will be filled in from env variables
		// if it is, just use that and don't prompt them
		settings.Username = ""
		settings.Password = ""
		fmt.Println("Please enter your logging dashboard credentials")
	}
	// if we remove the session token, the CLI will prompt for the
	// username/password normally. It will also set the username/password
	// on the settings object.
	sessionToken := settings.SessionToken
	settings.SessionToken = ""

	helpers.SignIn(settings)

	env := helpers.RetrieveEnvironment("pod", settings)
	var domain = env.Data.DNSName
	if domain == "" {
		domain = fmt.Sprintf("%s.catalyze.io", env.Data.Namespace)
	}

	urlString := fmt.Sprintf("https://%s/__es", domain)

	offset := time.Duration(hours)*time.Hour + time.Duration(minutes)*time.Minute + time.Duration(seconds)*time.Second
	timestamp := time.Now().In(time.UTC).Add(-1 * offset)

	from := 0
	query := &models.LogQuery{
		Fields: []string{"@timestamp", "message"},
		Query: &models.Query{
			Wildcard: map[string]string{
				"message": queryString,
			},
		},
		Filter: &models.FilterRange{
			Range: &models.RangeTimestamp{
				Timestamp: map[string]string{
					"gt": fmt.Sprintf("%04d-%02d-%02dT%02d:%02d:%02dZ", timestamp.Year(), timestamp.Month(), timestamp.Day(), timestamp.Hour(), timestamp.Minute(), timestamp.Second()),
				},
			},
		},
		Sort: &models.LogSort{
			Timestamp: map[string]string{
				"order": "asc",
			},
			Message: map[string]string{
				"order": "asc",
			},
		},
		From: from,
		Size: 50,
	}

	var tr = &http.Transport{
		TLSClientConfig: &tls.Config{
			MinVersion: tls.VersionTLS12,
		},
	}

	client := &http.Client{
		Transport: tr,
	}

	settings.SessionToken = sessionToken
	config.SaveSettings(settings)

	fmt.Println("        @timestamp       -        message")
	for {
		query.From = from
		b, err := json.Marshal(*query)
		if err != nil {
			panic(err)
		}
		reader := bytes.NewReader(b)

		req, _ := http.NewRequest("GET", fmt.Sprintf("%s/_search", urlString), reader)
		req.SetBasicAuth(settings.Username, settings.Password)

		resp, err := client.Do(req)
		if err != nil {
			fmt.Println(err.Error())
		}
		respBody, _ := ioutil.ReadAll(resp.Body)
		resp.Body.Close()
		if resp.StatusCode < 200 || resp.StatusCode >= 300 {
			fmt.Println(fmt.Errorf("%d %s", resp.StatusCode, string(respBody)).Error())
			os.Exit(1)
		}
		var logs models.Logs
		json.Unmarshal(respBody, &logs)
		for _, lh := range *logs.Hits.Hits {
			fmt.Printf("%s - %s\n", lh.Fields["@timestamp"][0], lh.Fields["message"][0])
		}
		if !tail {
			break
		}
		time.Sleep(2 * time.Second)
		from += len(*logs.Hits.Hits)
	}
}