Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cli/cmd/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ var _deleteCmd = &cobra.Command{
exit.Error(err)
}
} else {
// local only supports deploying 1 replica at a time so _flagDeleteForce will be ignored
deleteResponse, err = local.Delete(args[0], _flagDeleteKeepCache)
// local only supports deploying 1 replica at a time, so _flagDeleteForce is only useful when attempting to delete an API that has been deployed with different CLI version
deleteResponse, err = local.Delete(args[0], _flagDeleteKeepCache, _flagDeleteForce)
if err != nil {
exit.Error(err)
}
Expand Down
2 changes: 1 addition & 1 deletion cli/cmd/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ var _deployCmd = &cobra.Command{
exit.Error(err)
}

deployResponse, err = local.Deploy(env, configPath, projectFiles)
deployResponse, err = local.Deploy(env, configPath, projectFiles, _flagDeployDisallowPrompt)
if err != nil {
exit.Error(err)
}
Expand Down
53 changes: 51 additions & 2 deletions cli/local/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,40 @@ import (
"github.com/cortexlabs/cortex/pkg/lib/files"
"github.com/cortexlabs/cortex/pkg/lib/msgpack"
"github.com/cortexlabs/cortex/pkg/lib/pointer"
"github.com/cortexlabs/cortex/pkg/lib/prompt"
"github.com/cortexlabs/cortex/pkg/lib/sets/strset"
"github.com/cortexlabs/cortex/pkg/types/spec"
"github.com/cortexlabs/cortex/pkg/types/userconfig"
)

var _deploymentID = "local"

func UpdateAPI(apiConfig *userconfig.API, configPath string, projectID string, awsClient *aws.Client) (*spec.API, string, error) {
func UpdateAPI(apiConfig *userconfig.API, configPath string, projectID string, deployDisallowPrompt bool, awsClient *aws.Client) (*spec.API, string, error) {
var incompatibleVersion string
encounteredVersionMismatch := false
prevAPISpec, err := FindAPISpec(apiConfig.Name)
if err != nil {
if errors.GetKind(err) != ErrAPINotDeployed {
if errors.GetKind(err) == ErrCortexVersionMismatch {
encounteredVersionMismatch = true
if incompatibleVersion, err = GetVersionFromAPISpec(apiConfig.Name); err != nil {
return nil, "", err
}
if !deployDisallowPrompt {
minorVersionMismatch := strings.Join(strings.Split(incompatibleVersion, ".")[:2], ".")
prompt.YesOrExit(
fmt.Sprintf(
"api %s was deployed using CLI version %s but the current CLI version is %s; "+
"re-deploying %s with current CLI version %s might yield an unexpected outcome; any cached models won't be deleted\n\n"+
"it is recommended to download version %s of the CLI from https://docs.cortex.dev/v/%s/install, delete the API using version %s of the CLI and then re-deploy the API using the latest version of the CLI\n\n"+
"do you still want to re-deploy?",
apiConfig.Name, incompatibleVersion, consts.CortexVersion, apiConfig.Name, consts.CortexVersion, incompatibleVersion, minorVersionMismatch, incompatibleVersion),
"", "",
)
}
if err := DeleteAPI(apiConfig.Name); err != nil {
return nil, "", err
}
} else if errors.GetKind(err) != ErrAPINotDeployed {
return nil, "", err
}
}
Expand Down Expand Up @@ -88,6 +111,13 @@ func UpdateAPI(apiConfig *userconfig.API, configPath string, projectID string, a
}

if prevAPISpec == nil && len(prevAPIContainers) == 0 {
if encounteredVersionMismatch {
return newAPISpec, fmt.Sprintf(
"re-creating api %s with current CLI version %s",
newAPISpec.Name,
consts.CortexVersion,
), nil
}
return newAPISpec, fmt.Sprintf("creating %s", newAPISpec.Name), nil
}

Expand Down Expand Up @@ -202,6 +232,25 @@ func FindAPISpec(apiName string) (*spec.API, error) {
return nil, ErrorAPINotDeployed(apiName)
}

func GetVersionFromAPISpec(apiName string) (string, error) {
apiWorkspace := filepath.Join(_localWorkspaceDir, "apis", apiName)
if !files.IsDir(apiWorkspace) {
return "", ErrorAPINotDeployed(apiName)
}

filepaths, err := files.ListDirRecursive(apiWorkspace, false)
if err != nil {
return "", errors.Wrap(err, "api", apiName)
}

for _, specPath := range filepaths {
if strings.HasSuffix(filepath.Base(specPath), "-spec.msgpack") {
return GetVersionFromAPISpecFilePath(specPath), nil
}
}
return "", ErrorAPINotDeployed(apiName)
}

func GetVersionFromAPISpecFilePath(path string) string {
fileName := filepath.Base(path)
return strings.Split(fileName, "-")[0]
Expand Down
46 changes: 39 additions & 7 deletions cli/local/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,62 @@ package local

import (
"fmt"
"strings"

"github.com/cortexlabs/cortex/pkg/consts"
"github.com/cortexlabs/cortex/pkg/lib/docker"
"github.com/cortexlabs/cortex/pkg/lib/errors"
"github.com/cortexlabs/cortex/pkg/lib/prompt"
"github.com/cortexlabs/cortex/pkg/operator/schema"
"github.com/cortexlabs/cortex/pkg/types/spec"
)

func Delete(apiName string, keepCache bool) (schema.DeleteResponse, error) {
func Delete(apiName string, keepCache, deleteForce bool) (schema.DeleteResponse, error) {
_, err := docker.GetDockerClient()
if err != nil {
return schema.DeleteResponse{}, err
}

var apiSpec *spec.API = nil
if !keepCache {
if apiSpec, err = FindAPISpec(apiName); err != nil {
if apiSpec, err = FindAPISpec(apiName); err != nil {
if errors.GetKind(err) == ErrCortexVersionMismatch {
var incompatibleVersion string
if incompatibleVersion, err = GetVersionFromAPISpec(apiName); err != nil {
return schema.DeleteResponse{}, err
}
if !deleteForce {
minorVersionMismatch := strings.Join(strings.Split(incompatibleVersion, ".")[:2], ".")
prompt.YesOrExit(
fmt.Sprintf(
"api %s was deployed using CLI version %s but the current CLI version is %s; "+
"deleting %s with current CLI version %s might lead to an unexpected state; any cached models won't be deleted\n\n"+
"it is recommended to download version %s of the CLI from https://docs.cortex.dev/v/%s/install, delete the API using version %s of the CLI and then re-deploy the API using the latest version of the CLI\n\n"+
"do you still want to delete?",
apiName, incompatibleVersion, consts.CortexVersion, apiName, consts.CortexVersion, incompatibleVersion, minorVersionMismatch, incompatibleVersion),
"", "",
)
}
if err = DeleteAPI(apiName); err != nil {
return schema.DeleteResponse{}, err
}
return schema.DeleteResponse{
Message: fmt.Sprintf("deleting api %s with current CLI version %s", apiName, consts.CortexVersion),
}, nil
}

if !keepCache {
return schema.DeleteResponse{}, err
}
}

err = errors.FirstError(
DeleteAPI(apiName),
DeleteCachedModels(apiName, apiSpec.ModelIDs()),
)
if keepCache {
err = DeleteAPI(apiName)
} else {
err = errors.FirstError(
DeleteAPI(apiName),
DeleteCachedModels(apiName, apiSpec.ModelIDs()),
)
}
if err != nil {
return schema.DeleteResponse{}, err
}
Expand Down
4 changes: 2 additions & 2 deletions cli/local/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import (
"github.com/cortexlabs/cortex/pkg/types/spec"
)

func Deploy(env cliconfig.Environment, configPath string, projectFileList []string) (schema.DeployResponse, error) {
func Deploy(env cliconfig.Environment, configPath string, projectFileList []string, deployDisallowPrompt bool) (schema.DeployResponse, error) {
configFileName := filepath.Base(configPath)

_, err := docker.GetDockerClient()
Expand Down Expand Up @@ -80,7 +80,7 @@ func Deploy(env cliconfig.Environment, configPath string, projectFileList []stri

results := make([]schema.DeployResult, len(apiConfigs))
for i, apiConfig := range apiConfigs {
api, msg, err := UpdateAPI(&apiConfig, configPath, projectID, awsClient)
api, msg, err := UpdateAPI(&apiConfig, configPath, projectID, deployDisallowPrompt, awsClient)
results[i].Message = msg
if err != nil {
results[i].Error = errors.Message(err)
Expand Down