Skip to content

Commit 1b737d4

Browse files
vishalbolludeliahu
authored andcommitted
List active Cortex deployments (#268)
1 parent 48224b8 commit 1b737d4

File tree

12 files changed

+208
-13
lines changed

12 files changed

+208
-13
lines changed

cli/cmd/get.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ func init() {
4747
addWatchFlag(getCmd)
4848
addSummaryFlag(getCmd)
4949
addVerboseFlag(getCmd)
50+
addAllDeploymentsFlag(getCmd)
5051
// addResourceTypesToHelp(getCmd)
5152
}
5253

@@ -63,6 +64,10 @@ var getCmd = &cobra.Command{
6364
}
6465

6566
func runGet(cmd *cobra.Command, args []string) (string, error) {
67+
if flagAllDeployments || !IsAppNameSpecified() {
68+
return getDeploymentsResponse()
69+
}
70+
6671
resourcesRes, err := getResourcesResponse()
6772
if err != nil {
6873
return "", err
@@ -109,6 +114,42 @@ func runGet(cmd *cobra.Command, args []string) (string, error) {
109114
return "", errors.New("too many args") // unexpected
110115
}
111116

117+
func getDeploymentsResponse() (string, error) {
118+
httpResponse, err := HTTPGet("/deployments", map[string]string{})
119+
if err != nil {
120+
return "", err
121+
}
122+
123+
var resourcesRes schema.GetDeploymentsResponse
124+
if err = json.Unmarshal(httpResponse, &resourcesRes); err != nil {
125+
return "", err
126+
}
127+
128+
if len(resourcesRes.Deployments) == 0 {
129+
return "No deployments found", nil
130+
}
131+
132+
rows := make([][]interface{}, len(resourcesRes.Deployments))
133+
for idx, deployment := range resourcesRes.Deployments {
134+
rows[idx] = []interface{}{
135+
deployment.Name,
136+
deployment.Status.String(),
137+
libtime.Since(&deployment.LastUpdated),
138+
}
139+
}
140+
141+
t := table.Table{
142+
Headers: []table.Header{
143+
{Title: "NAME", MaxWidth: 32},
144+
{Title: "STATUS", MaxWidth: 21},
145+
{Title: "LAST UPDATED"},
146+
},
147+
Rows: rows,
148+
}
149+
150+
return table.MustFormat(t), nil
151+
}
152+
112153
func getResourcesResponse() (*schema.GetResourcesResponse, error) {
113154
appName, err := AppNameFromFlagOrConfig()
114155
if err != nil {

cli/cmd/lib_config_reader.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,7 @@ func AppNameFromFlagOrConfig() (string, error) {
106106

107107
return appName, nil
108108
}
109+
110+
func IsAppNameSpecified() bool {
111+
return flagAppName != "" || appRootOrBlank() != ""
112+
}

cli/cmd/root.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ var flagWatch bool
4040
var flagAppName string
4141
var flagVerbose bool
4242
var flagSummary bool
43+
var flagAllDeployments bool
4344

4445
var configFileExts = []string{"yaml", "yml"}
4546

@@ -106,6 +107,10 @@ func addSummaryFlag(cmd *cobra.Command) {
106107
cmd.PersistentFlags().BoolVarP(&flagSummary, "summary", "s", false, "show summarized output")
107108
}
108109

110+
func addAllDeploymentsFlag(cmd *cobra.Command) {
111+
getCmd.PersistentFlags().BoolVarP(&flagAllDeployments, "all-deployments", "a", false, "list all deployments")
112+
}
113+
109114
var resourceTypesHelp = fmt.Sprintf("\nResource Types:\n %s\n", strings.Join(resource.VisibleTypes.StringList(), "\n "))
110115

111116
func addResourceTypesToHelp(cmd *cobra.Command) {

docs/cluster/cli.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ Usage:
2525
cortex get [RESOURCE_TYPE] [RESOURCE_NAME] [flags]
2626
2727
Flags:
28+
-a, --all-deployments list all deployments
2829
-d, --deployment string deployment name
2930
-e, --env string environment (default "dev")
3031
-h, --help help for get
@@ -33,7 +34,7 @@ Flags:
3334
-w, --watch re-run the command every second
3435
```
3536

36-
The `get` command displays the current state of all resources on the cluster. Specifying a resource name provides the state of the particular resource. A detailed view of the configuration and additional metdata of a specific resource can be retrieved by adding the `-v` or `--verbose` flag. Using the `-s` or `--summary` flag will show a summarized view of all resource statuses.
37+
The `get` command displays the current state of all resources on the cluster. Specifying a resource name provides the state of the particular resource. A detailed view of the configuration and additional metdata of a specific resource can be retrieved by adding the `-v` or `--verbose` flag. Using the `-s` or `--summary` flag will show a summarized view of all resource statuses. A list of deployments can be displayed by specifying the `-a` or `--all-deployments` flag.
3738

3839
## logs
3940

pkg/operator/api/context/context.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
type Context struct {
3030
ID string `json:"id"`
3131
Key string `json:"key"`
32+
CreatedEpoch int64 `json:"created_epoch"`
3233
CortexConfig *config.CortexConfig `json:"cortex_config"`
3334
DatasetVersion string `json:"dataset_version"`
3435
Root string `json:"root"`
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
Copyright 2019 Cortex Labs, Inc.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package resource
18+
19+
type DeploymentStatus int
20+
21+
const (
22+
UnknownDeploymentStatus DeploymentStatus = iota
23+
UpdatedDeploymentStatus
24+
UpdatingDeploymentStatus
25+
ErrorDeploymentStatus
26+
)
27+
28+
var deploymentStatuses = []string{
29+
"unknown",
30+
"updated",
31+
"updating",
32+
"error",
33+
}
34+
35+
func DeploymentStatusFromString(s string) DeploymentStatus {
36+
for i := 0; i < len(deploymentStatuses); i++ {
37+
if s == deploymentStatuses[i] {
38+
return DeploymentStatus(i)
39+
}
40+
}
41+
return UnknownDeploymentStatus
42+
}
43+
44+
func DeploymentStatusStrings() []string {
45+
return deploymentStatuses[1:]
46+
}
47+
48+
func (t DeploymentStatus) String() string {
49+
return deploymentStatuses[t]
50+
}
51+
52+
// MarshalText satisfies TextMarshaler
53+
func (t DeploymentStatus) MarshalText() ([]byte, error) {
54+
return []byte(t.String()), nil
55+
}
56+
57+
// UnmarshalText satisfies TextUnmarshaler
58+
func (t *DeploymentStatus) UnmarshalText(text []byte) error {
59+
enum := string(text)
60+
for i := 0; i < len(deploymentStatuses); i++ {
61+
if enum == deploymentStatuses[i] {
62+
*t = DeploymentStatus(i)
63+
return nil
64+
}
65+
}
66+
67+
*t = UnknownDeploymentStatus
68+
return nil
69+
}
70+
71+
// UnmarshalBinary satisfies BinaryUnmarshaler
72+
// Needed for msgpack
73+
func (t *DeploymentStatus) UnmarshalBinary(data []byte) error {
74+
return t.UnmarshalText(data)
75+
}
76+
77+
// MarshalBinary satisfies BinaryMarshaler
78+
func (t DeploymentStatus) MarshalBinary() ([]byte, error) {
79+
return []byte(t.String()), nil
80+
}

pkg/operator/api/schema/schema.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ limitations under the License.
1717
package schema
1818

1919
import (
20+
"time"
21+
2022
"github.com/cortexlabs/cortex/pkg/operator/api/context"
2123
"github.com/cortexlabs/cortex/pkg/operator/api/resource"
2224
)
@@ -41,6 +43,16 @@ type GetResourcesResponse struct {
4143
APIsBaseURL string `json:"apis_base_url"`
4244
}
4345

46+
type Deployment struct {
47+
Name string `json:"name"`
48+
Status resource.DeploymentStatus `json:"status"`
49+
LastUpdated time.Time `json:"last_updated"`
50+
}
51+
52+
type GetDeploymentsResponse struct {
53+
Deployments []Deployment `json:"deployments"`
54+
}
55+
4456
type GetAggregateResponse struct {
4557
Value []byte `json:"value"`
4658
}

pkg/operator/context/context.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"path/filepath"
2121
"sort"
2222
"strings"
23+
"time"
2324

2425
"github.com/cortexlabs/cortex/pkg/consts"
2526
"github.com/cortexlabs/cortex/pkg/lib/configreader"
@@ -122,6 +123,7 @@ func New(
122123
ignoreCache bool,
123124
) (*context.Context, error) {
124125
ctx := &context.Context{}
126+
ctx.CreatedEpoch = time.Now().Unix()
125127

126128
ctx.CortexConfig = config.Cortex
127129

pkg/operator/endpoints/deploy.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/cortexlabs/cortex/pkg/lib/files"
2424
"github.com/cortexlabs/cortex/pkg/lib/zip"
2525
"github.com/cortexlabs/cortex/pkg/operator/api/context"
26+
"github.com/cortexlabs/cortex/pkg/operator/api/resource"
2627
"github.com/cortexlabs/cortex/pkg/operator/api/schema"
2728
"github.com/cortexlabs/cortex/pkg/operator/api/userconfig"
2829
"github.com/cortexlabs/cortex/pkg/operator/config"
@@ -61,12 +62,14 @@ func Deploy(w http.ResponseWriter, r *http.Request) {
6162
fullCtxMatch = true
6263
}
6364

64-
isUpdating, err := workloads.IsDeploymentUpdating(ctx.App.Name)
65+
deploymentStatus, err := workloads.GetDeploymentStatus(ctx.App.Name)
6566
if err != nil {
6667
RespondError(w, err)
6768
return
6869
}
6970

71+
isUpdating := deploymentStatus == resource.UpdatingDeploymentStatus
72+
7073
if isUpdating {
7174
if fullCtxMatch {
7275
respondDeploy(w, ResDeploymentUpToDateUpdating)

pkg/operator/endpoints/deployments.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
Copyright 2019 Cortex Labs, Inc.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package endpoints
18+
19+
import (
20+
"net/http"
21+
"time"
22+
23+
"github.com/cortexlabs/cortex/pkg/operator/api/schema"
24+
"github.com/cortexlabs/cortex/pkg/operator/workloads"
25+
)
26+
27+
func GetDeployments(w http.ResponseWriter, r *http.Request) {
28+
currentContexts := workloads.CurrentContexts()
29+
deployments := make([]schema.Deployment, len(currentContexts))
30+
for i, ctx := range currentContexts {
31+
deployments[i].Name = ctx.App.Name
32+
status, _ := workloads.GetDeploymentStatus(ctx.App.Name)
33+
deployments[i].Status = status
34+
deployments[i].LastUpdated = time.Unix(ctx.CreatedEpoch, 0)
35+
}
36+
37+
response := schema.GetDeploymentsResponse{
38+
Deployments: deployments,
39+
}
40+
41+
Respond(w, response)
42+
}

0 commit comments

Comments
 (0)