From b413b924277be54d02d47c303f6240ee98a36af3 Mon Sep 17 00:00:00 2001 From: David Eliahu Date: Sun, 6 Jun 2021 13:35:46 -0700 Subject: [PATCH 1/2] Misc UI improvements --- cli/cmd/cluster.go | 8 ++-- cli/cmd/delete.go | 2 +- cli/cmd/deploy.go | 58 +------------------------- cli/cmd/lib_cluster_config.go | 29 +++++-------- cli/cmd/logs.go | 2 +- docs/clients/cli.md | 4 +- docs/clusters/observability/logging.md | 4 +- 7 files changed, 21 insertions(+), 86 deletions(-) diff --git a/cli/cmd/cluster.go b/cli/cmd/cluster.go index b26744e872..f8f138f3d3 100644 --- a/cli/cmd/cluster.go +++ b/cli/cmd/cluster.go @@ -896,8 +896,7 @@ func printInfoPricing(infoResponse *schema.InfoResponse, clusterConfig clusterco totalInstancePrice += nodeInfo.Price } - rows = append(rows, []interface{}{fmt.Sprintf("nodegroup %s: %d (out of %d) %s for your apis", ng.Name, numInstances, ng.MaxInstances, s.PluralS("instance", numInstances)), s.DollarsAndTenthsOfCents(totalInstancePrice) + " total"}) - rows = append(rows, []interface{}{fmt.Sprintf("nodegroup %s: %d (out of %d) %dgb ebs %s for your apis", ng.Name, numInstances, ng.MaxInstances, ng.InstanceVolumeSize, s.PluralS("volume", numInstances)), s.DollarsAndTenthsOfCents(totalEBSPrice) + " total"}) + rows = append(rows, []interface{}{fmt.Sprintf("nodegroup %s: %d (out of %d) %s", ng.Name, numInstances, ng.MaxInstances, s.PluralS("instance", numInstances)), s.DollarsAndTenthsOfCents(totalInstancePrice+totalEBSPrice) + " total"}) totalNodeGroupsPrice += totalEBSPrice + totalInstancePrice } @@ -911,9 +910,8 @@ func printInfoPricing(infoResponse *schema.InfoResponse, clusterConfig clusterco totalPrice := eksPrice + totalNodeGroupsPrice + 2*(operatorInstancePrice+operatorEBSPrice) + metricsEBSPrice + nlbPrice*2 + natTotalPrice fmt.Printf(console.Bold("\nyour cluster currently costs %s per hour\n\n"), s.DollarsAndCents(totalPrice)) - rows = append(rows, []interface{}{"2 t3.medium instances for cortex", s.DollarsMaxPrecision(operatorInstancePrice * 2)}) - rows = append(rows, []interface{}{"2 20gb ebs volumes for the operator", s.DollarsAndTenthsOfCents(operatorEBSPrice * 2)}) - rows = append(rows, []interface{}{"1 40+2gb ebs volumes for metrics (prometheus and grafana)", s.DollarsAndTenthsOfCents(metricsEBSPrice)}) + operatorPrice := 2*(operatorInstancePrice+operatorEBSPrice) + metricsEBSPrice + rows = append(rows, []interface{}{"2 t3.medium instances (cortex system)", s.DollarsAndTenthsOfCents(operatorPrice)}) rows = append(rows, []interface{}{"2 network load balancers", s.DollarsMaxPrecision(nlbPrice*2) + " total"}) if clusterConfig.NATGateway == clusterconfig.SingleNATGateway { diff --git a/cli/cmd/delete.go b/cli/cmd/delete.go index 96fc9f4d4a..84e46b3adb 100644 --- a/cli/cmd/delete.go +++ b/cli/cmd/delete.go @@ -47,7 +47,7 @@ func deleteInit() { var _deleteCmd = &cobra.Command{ Use: "delete API_NAME [JOB_ID]", - Short: "delete any kind of api or stop a batch job", + Short: "delete an api or stop a job", Args: cobra.RangeArgs(1, 2), Run: func(cmd *cobra.Command, args []string) { envName, err := getEnvFromFlag(_flagDeleteEnv) diff --git a/cli/cmd/deploy.go b/cli/cmd/deploy.go index f70ea3b77b..e263fe0cda 100644 --- a/cli/cmd/deploy.go +++ b/cli/cmd/deploy.go @@ -25,12 +25,9 @@ import ( "github.com/cortexlabs/cortex/pkg/lib/exit" "github.com/cortexlabs/cortex/pkg/lib/files" libjson "github.com/cortexlabs/cortex/pkg/lib/json" - "github.com/cortexlabs/cortex/pkg/lib/pointer" "github.com/cortexlabs/cortex/pkg/lib/print" - "github.com/cortexlabs/cortex/pkg/lib/table" "github.com/cortexlabs/cortex/pkg/lib/telemetry" "github.com/cortexlabs/cortex/pkg/operator/schema" - "github.com/cortexlabs/cortex/pkg/types/userconfig" "github.com/spf13/cobra" ) @@ -106,10 +103,7 @@ var _deployCmd = &cobra.Command{ } fmt.Print(string(bytes)) case flags.PrettyOutputType: - message, err := deployMessage(deployResults, env.Name) - if err != nil { - exit.Error(err) - } + message := mergeResultMessages(deployResults) if didAnyResultsError(deployResults) { print.StderrBoldFirstBlock(message) } else { @@ -155,21 +149,6 @@ func getDeploymentBytes(configPath string) (map[string][]byte, error) { return uploadBytes, nil } -func deployMessage(results []schema.DeployResult, envName string) (string, error) { - statusMessage := mergeResultMessages(results) - - if didAllResultsError(results) { - return statusMessage, nil - } - - apiCommandsMessage, err := getAPICommandsMessage(results, envName) - if err != nil { - return "", err - } - - return statusMessage + "\n\n" + apiCommandsMessage, nil -} - func mergeResultMessages(results []schema.DeployResult) string { var okMessages []string var errMessages []string @@ -215,38 +194,3 @@ func didAnyResultsError(results []schema.DeployResult) bool { } return false } - -func getAPICommandsMessage(results []schema.DeployResult, envName string) (string, error) { - apiName := "" - if len(results) == 1 { - apiName = results[0].API.Spec.Name - } - - defaultEnv, err := getDefaultEnv() - if err != nil { - return "", err - } - var envArg string - if defaultEnv == nil || envName != *defaultEnv { - envArg = " --env " + envName - } - - var items table.KeyValuePairs - items.Add("cortex get"+envArg, "(show api statuses)") - items.Add(fmt.Sprintf("cortex get %s%s", apiName, envArg), "(show api info)") - - for _, result := range results { - if len(result.Error) > 0 { - continue - } - if result.API != nil && result.API.Spec.Kind == userconfig.RealtimeAPIKind { - items.Add(fmt.Sprintf("cortex logs %s%s", apiName, envArg), "(access logs)") - break - } - } - - return strings.TrimSpace(items.String(&table.KeyValuePairOpts{ - Delimiter: pointer.String(""), - NumSpaces: pointer.Int(2), - })), nil -} diff --git a/cli/cmd/lib_cluster_config.go b/cli/cmd/lib_cluster_config.go index 2f4c8df22b..29304a4f38 100644 --- a/cli/cmd/lib_cluster_config.go +++ b/cli/cmd/lib_cluster_config.go @@ -185,40 +185,33 @@ func confirmInstallClusterConfig(clusterConfig *clusterconfig.Config, awsClient apiEBSPrice += libmath.MaxFloat64(0, (aws.EBSMetadatas[clusterConfig.Region][ng.InstanceVolumeType.String()].PriceThroughput-125)*float64(*ng.InstanceVolumeThroughput)/30/24) } - totalMinPrice += float64(ng.MinInstances) * (apiInstancePrice + apiEBSPrice) totalMaxPrice += float64(ng.MaxInstances) * (apiInstancePrice + apiEBSPrice) - instanceStr := "instances" - volumeStr := "volumes" - if ng.MinInstances == 1 && ng.MaxInstances == 1 { - instanceStr = "instance" - volumeStr = "volume" - } - workerInstanceStr := fmt.Sprintf("nodegroup %s: %d - %d %s %s for your apis", ng.Name, ng.MinInstances, ng.MaxInstances, ng.InstanceType, instanceStr) - ebsInstanceStr := fmt.Sprintf("nodegroup %s: %d - %d %dgb ebs %s for your apis", ng.Name, ng.MinInstances, ng.MaxInstances, ng.InstanceVolumeSize, volumeStr) + workerInstanceStr := fmt.Sprintf("nodegroup %s: %d-%d %s instances", ng.Name, ng.MinInstances, ng.MaxInstances, ng.InstanceType) if ng.MinInstances == ng.MaxInstances { - workerInstanceStr = fmt.Sprintf("nodegroup %s: %d %s %s for your apis", ng.Name, ng.MinInstances, ng.InstanceType, instanceStr) - ebsInstanceStr = fmt.Sprintf("nodegroup %s:%d %dgb ebs %s for your apis", ng.Name, ng.MinInstances, ng.InstanceVolumeSize, volumeStr) + workerInstanceStr = fmt.Sprintf("nodegroup %s: %d %s %s", ng.Name, ng.MinInstances, ng.InstanceType, s.PluralS("instance", ng.MinInstances)) } - workerPriceStr := s.DollarsMaxPrecision(apiInstancePrice) + " each" + workerPriceStr := s.DollarsAndTenthsOfCents(apiInstancePrice+apiEBSPrice) + " each" if ng.Spot { ngNameToSpotInstancesUsed[ng.Name]++ spotPrice, err := awsClient.SpotInstancePrice(ng.InstanceType) workerPriceStr += " (spot pricing unavailable)" if err == nil && spotPrice != 0 { - workerPriceStr = fmt.Sprintf("%s - %s each (varies based on spot price)", s.DollarsMaxPrecision(spotPrice), s.DollarsMaxPrecision(apiInstancePrice)) - totalMinPrice = fixedPrice + float64(ng.MinInstances)*(spotPrice+apiEBSPrice) + workerPriceStr = fmt.Sprintf("%s - %s each (varies based on spot price)", s.DollarsAndTenthsOfCents(spotPrice+apiEBSPrice), s.DollarsAndTenthsOfCents(apiInstancePrice+apiEBSPrice)) + totalMinPrice += float64(ng.MinInstances) * (spotPrice + apiEBSPrice) + } else { + totalMinPrice += float64(ng.MinInstances) * (apiInstancePrice + apiEBSPrice) } + } else { + totalMinPrice += float64(ng.MinInstances) * (apiInstancePrice + apiEBSPrice) } rows = append(rows, []interface{}{workerInstanceStr, workerPriceStr}) - rows = append(rows, []interface{}{ebsInstanceStr, s.DollarsAndTenthsOfCents(apiEBSPrice) + " each"}) } - rows = append(rows, []interface{}{"2 t3.medium instances for cortex", s.DollarsMaxPrecision(operatorInstancePrice * 2)}) - rows = append(rows, []interface{}{"2 20gb ebs volumes for the operator", s.DollarsAndTenthsOfCents(operatorEBSPrice * 2)}) - rows = append(rows, []interface{}{"1 40+2gb ebs volumes for metrics (prometheus and grafana)", s.DollarsAndTenthsOfCents(metricsEBSPrice)}) + operatorPrice := 2*(operatorInstancePrice+operatorEBSPrice) + metricsEBSPrice + rows = append(rows, []interface{}{"2 t3.medium instances (cortex system)", s.DollarsAndTenthsOfCents(operatorPrice)}) rows = append(rows, []interface{}{"2 network load balancers", s.DollarsMaxPrecision(nlbPrice) + " each"}) if clusterConfig.NATGateway == clusterconfig.SingleNATGateway { diff --git a/cli/cmd/logs.go b/cli/cmd/logs.go index f7fd6e1286..e14bf487fc 100644 --- a/cli/cmd/logs.go +++ b/cli/cmd/logs.go @@ -46,7 +46,7 @@ func logsInit() { var _logsCmd = &cobra.Command{ Use: "logs API_NAME [JOB_ID]", - Short: "get the logs for an API or a job", + Short: "get the logs for a workload", Args: cobra.RangeArgs(1, 2), Run: func(cmd *cobra.Command, args []string) { envName, err := getEnvFromFlag(_flagLogsEnv) diff --git a/docs/clients/cli.md b/docs/clients/cli.md index 5b4c843f4c..1e060cda88 100644 --- a/docs/clients/cli.md +++ b/docs/clients/cli.md @@ -35,7 +35,7 @@ Flags: ## logs ```text -get the logs for an API or a job +get the logs for a workload Usage: cortex logs API_NAME [JOB_ID] [flags] @@ -65,7 +65,7 @@ Flags: ## delete ```text -delete any kind of api or stop a batch job +delete an api or stop a job Usage: cortex delete API_NAME [JOB_ID] [flags] diff --git a/docs/clusters/observability/logging.md b/docs/clusters/observability/logging.md index ea223f3a59..a10bcd6ad9 100644 --- a/docs/clusters/observability/logging.md +++ b/docs/clusters/observability/logging.md @@ -50,9 +50,9 @@ fields @timestamp, message | limit 1000 ``` -## Streaming logs for an API or a running job +## Streaming logs from the CLI -You can stream logs directly from a random pod of an API or a running job to iterate and debug quickly. These logs will not be as comprehensive as the logs that are available in CloudWatch. +You can stream logs directly from a random pod of a running workload to iterate and debug quickly. These logs will not be as comprehensive as the logs that are available in CloudWatch. ```bash # RealtimeAPI From f9c8da725223144a20a1a3b92b965b5d02db2094 Mon Sep 17 00:00:00 2001 From: David Eliahu Date: Mon, 7 Jun 2021 10:40:06 -0700 Subject: [PATCH 2/2] Misc pod renaming --- pkg/operator/operator/workload_logging.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/operator/operator/workload_logging.go b/pkg/operator/operator/workload_logging.go index 47d97c405e..a858805d6c 100644 --- a/pkg/operator/operator/workload_logging.go +++ b/pkg/operator/operator/workload_logging.go @@ -207,13 +207,13 @@ func waitForPodToBeNotPending(podName string, cancelListener chan struct{}, sock return false } if pod == nil { - writeAndCloseSocket(socket, "unable to find replica/worker") + writeAndCloseSocket(socket, "unable to find pod") return false } podStatus := k8s.GetPodStatus(pod) if podStatus == k8s.PodStatusPending { if !wrotePending { - writeString(socket, "waiting for replica/worker to initialize ...\n") + writeString(socket, "waiting for pod to initialize ...\n") } wrotePending = true timer.Reset(_pendingPodCheckInterval) @@ -294,7 +294,7 @@ func StreamLogsFromRandomPod(podSearchLabels map[string]string, socket *websocke return } if len(pods) == 0 { - writeAndCloseSocket(socket, "there are currently no replicas/workers running for this api or job; please visit your logging dashboard for historical logs\n") + writeAndCloseSocket(socket, "there are currently no pods running for this workload; please visit your logging dashboard for historical logs\n") return }