diff --git a/cli/cmd/delete.go b/cli/cmd/delete.go index 89ee3669d1..d583b6615c 100644 --- a/cli/cmd/delete.go +++ b/cli/cmd/delete.go @@ -46,10 +46,11 @@ var deleteCmd = &cobra.Command{ if len(args) == 1 { appName = args[0] } else { - appName, err = appNameFromConfig() + config, err := readConfig() if err != nil { errors.Exit(err) } + appName = config.App.Name } params := map[string]string{ diff --git a/cli/cmd/deploy.go b/cli/cmd/deploy.go index 700cf018ec..528af80123 100644 --- a/cli/cmd/deploy.go +++ b/cli/cmd/deploy.go @@ -32,6 +32,7 @@ import ( "github.com/cortexlabs/cortex/pkg/operator/api/userconfig" ) +var MaxProjectSize = 1024 * 1024 * 50 var flagDeployForce bool func init() { @@ -51,7 +52,7 @@ var deployCmd = &cobra.Command{ func deploy(force bool, ignoreCache bool) { root := mustAppRoot() - _, err := appNameFromConfig() // Check proper cortex.yaml + config, err := readConfig() // Check proper cortex.yaml if err != nil { errors.Exit(err) } @@ -66,34 +67,43 @@ func deploy(force bool, ignoreCache bool) { errors.Exit(errors.Wrap(err, "cortex.yaml", userconfig.ErrorReadConfig().Error())) } - projectPaths, err := files.ListDirRecursive(root, false, - files.IgnoreCortexYAML, - files.IgnoreHiddenFiles, - files.IgnoreHiddenFolders, - files.IgnorePythonGeneratedFiles, - ) - if err != nil { - errors.Exit(err) + uploadBytes := map[string][]byte{ + "cortex.yaml": configBytes, } - projectZipBytes, err := zip.ToMem(&zip.Input{ - FileLists: []zip.FileListInput{ - { - Sources: projectPaths, - RemovePrefix: root, + if config.AreProjectFilesRequired() { + projectPaths, err := files.ListDirRecursive(root, false, + files.IgnoreCortexYAML, + files.IgnoreHiddenFiles, + files.IgnoreHiddenFolders, + files.IgnorePythonGeneratedFiles, + ) + if err != nil { + errors.Exit(err) + } + + projectZipBytes, err := zip.ToMem(&zip.Input{ + FileLists: []zip.FileListInput{ + { + Sources: projectPaths, + RemovePrefix: root, + }, }, - }, - }) + }) - if err != nil { - errors.Exit(errors.Wrap(err, "failed to zip project folder")) + if err != nil { + errors.Exit(errors.Wrap(err, "failed to zip project folder")) + } + + if len(projectZipBytes) > MaxProjectSize { + errors.Exit(errors.New("zipped project folder exceeds " + s.Int(MaxProjectSize) + " bytes")) + } + + uploadBytes["project.zip"] = projectZipBytes } uploadInput := &HTTPUploadInput{ - Bytes: map[string][]byte{ - "cortex.yaml": configBytes, - "project.zip": projectZipBytes, - }, + Bytes: uploadBytes, } response, err := HTTPUpload("/deploy", uploadInput, params) diff --git a/cli/cmd/lib_config_reader.go b/cli/cmd/lib_config_reader.go index e610a96276..2430d50496 100644 --- a/cli/cmd/lib_config_reader.go +++ b/cli/cmd/lib_config_reader.go @@ -66,9 +66,13 @@ func pythonPaths(dir string) []string { return pyPaths } -func appNameFromConfig() (string, error) { +func readConfig() (*userconfig.Config, error) { appRoot := mustAppRoot() - return userconfig.ReadAppName(filepath.Join(appRoot, "cortex.yaml"), "cortex.yaml") + config, err := userconfig.ReadConfigFile(filepath.Join(appRoot, "cortex.yaml"), "cortex.yaml") + if err != nil { + return nil, err + } + return config, nil } func AppNameFromFlagOrConfig() (string, error) { @@ -76,12 +80,12 @@ func AppNameFromFlagOrConfig() (string, error) { return flagAppName, nil } - appName, err := appNameFromConfig() + config, err := readConfig() if err != nil { return "", err } - return appName, nil + return config.App.Name, nil } func IsAppNameSpecified() bool { diff --git a/pkg/operator/api/userconfig/apis.go b/pkg/operator/api/userconfig/apis.go index 944d05dbcb..5cd1f921b6 100644 --- a/pkg/operator/api/userconfig/apis.go +++ b/pkg/operator/api/userconfig/apis.go @@ -300,6 +300,10 @@ func (api *API) Validate(projectFileMap map[string][]byte) error { return nil } +func (api *API) AreProjectFilesRequired() bool { + return api.RequestHandler != nil +} + func (api *API) GetResourceType() resource.Type { return resource.APIType } @@ -311,3 +315,12 @@ func (apis APIs) Names() []string { } return names } + +func (apis APIs) AreProjectFilesRequired() bool { + for _, api := range apis { + if api.AreProjectFilesRequired() { + return true + } + } + return false +} diff --git a/pkg/operator/api/userconfig/config.go b/pkg/operator/api/userconfig/config.go index 2be02c1a0c..aca07a0a02 100644 --- a/pkg/operator/api/userconfig/config.go +++ b/pkg/operator/api/userconfig/config.go @@ -37,15 +37,21 @@ var typeFieldValidation = &cr.StructFieldValidation{ } func (config *Config) Validate(projectBytes []byte) error { - if err := config.App.Validate(); err != nil { - return err - } + err := config.App.Validate() - projectFileMap, err := zip.UnzipMemToMem(projectBytes) if err != nil { return err } + projectFileMap := make(map[string][]byte) + + if config.AreProjectFilesRequired() { + projectFileMap, err = zip.UnzipMemToMem(projectBytes) + if err != nil { + return err + } + } + if config.APIs != nil { if err := config.APIs.Validate(projectFileMap); err != nil { return err @@ -55,6 +61,10 @@ func (config *Config) Validate(projectBytes []byte) error { return nil } +func (config *Config) AreProjectFilesRequired() bool { + return config.APIs.AreProjectFilesRequired() +} + func New(filePath string, configBytes []byte) (*Config, error) { var err error @@ -118,16 +128,16 @@ func New(filePath string, configBytes []byte) (*Config, error) { return config, nil } -func ReadAppName(filePath string, relativePath string) (string, error) { +func ReadConfigFile(filePath string, relativePath string) (*Config, error) { configBytes, err := files.ReadFileBytes(filePath) if err != nil { - return "", errors.Wrap(err, relativePath, ErrorReadConfig().Error()) + return nil, errors.Wrap(err, relativePath, ErrorReadConfig().Error()) } config, err := New(relativePath, configBytes) if err != nil { - return "", err + return nil, err } - return config.App.Name, nil + return config, nil } diff --git a/pkg/operator/context/context.go b/pkg/operator/context/context.go index 79a432e6c1..453516c9e2 100644 --- a/pkg/operator/context/context.go +++ b/pkg/operator/context/context.go @@ -69,14 +69,11 @@ func New( } ctx.APIs = apis - for _, api := range ctx.APIs { - if api.RequestHandler != nil { - ctx.ProjectID = projectID - ctx.ProjectKey = filepath.Join(consts.ProjectsDir, ctx.ProjectID+".zip") - if err = config.AWS.UploadBytesToS3(projectBytes, ctx.ProjectKey); err != nil { - return nil, err - } - break + if userconf.AreProjectFilesRequired() { + ctx.ProjectID = projectID + ctx.ProjectKey = filepath.Join(consts.ProjectsDir, ctx.ProjectID+".zip") + if err = config.AWS.UploadBytesToS3(projectBytes, ctx.ProjectKey); err != nil { + return nil, err } } diff --git a/pkg/operator/endpoints/deploy.go b/pkg/operator/endpoints/deploy.go index 9dda4cbe5a..968563c7ec 100644 --- a/pkg/operator/endpoints/deploy.go +++ b/pkg/operator/endpoints/deploy.go @@ -48,10 +48,6 @@ func Deploy(w http.ResponseWriter, r *http.Request) { } projectBytes, err := files.ReadReqFile(r, "project.zip") - if err != nil { - RespondError(w, errors.WithStack(err)) - return - } userconf, err := userconfig.New("cortex.yaml", configBytes) if err != nil { @@ -65,22 +61,12 @@ func Deploy(w http.ResponseWriter, r *http.Request) { return } - if len(projectBytes) == 0 { - RespondError(w, ErrorFormFileMustBeProvided("project.zip")) - return - } - ctx, err := ocontext.New(userconf, projectBytes, ignoreCache) if err != nil { RespondError(w, err) return } - if err != nil { - RespondError(w, err) - return - } - err = workloads.PopulateWorkloadIDs(ctx) if err != nil { RespondError(w, err)