Skip to content

Commit e31847f

Browse files
authored
Avoid docker mounting to support CLI commands inside of a docker container (#1370)
1 parent 5a8c4f7 commit e31847f

33 files changed

+1356
-588
lines changed

cli/cluster/lib_http_client.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ import (
2727
"time"
2828

2929
"github.com/cortexlabs/cortex/pkg/consts"
30+
"github.com/cortexlabs/cortex/pkg/lib/archive"
3031
"github.com/cortexlabs/cortex/pkg/lib/errors"
3132
"github.com/cortexlabs/cortex/pkg/lib/files"
3233
"github.com/cortexlabs/cortex/pkg/lib/json"
33-
"github.com/cortexlabs/cortex/pkg/lib/zip"
3434
"github.com/cortexlabs/cortex/pkg/operator/schema"
3535
)
3636

@@ -154,8 +154,8 @@ func addFileToMultipart(fileName string, writer *multipart.Writer, reader io.Rea
154154
return nil
155155
}
156156

157-
func HTTPUploadZip(operatorConfig OperatorConfig, endpoint string, zipInput *zip.Input, fileName string, qParams ...map[string]string) ([]byte, error) {
158-
zipBytes, err := zip.ToMem(zipInput)
157+
func HTTPUploadZip(operatorConfig OperatorConfig, endpoint string, zipInput *archive.Input, fileName string, qParams ...map[string]string) ([]byte, error) {
158+
zipBytes, _, err := archive.ZipToMem(zipInput)
159159
if err != nil {
160160
return nil, errors.Wrap(err, "failed to zip configuration file")
161161
}

cli/cmd/cluster.go

Lines changed: 76 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package cmd
1919
import (
2020
"fmt"
2121
"os"
22+
"path/filepath"
2223
"strings"
2324
"time"
2425

@@ -158,7 +159,7 @@ var _upCmd = &cobra.Command{
158159
}
159160
}
160161

161-
out, exitCode, err := runManagerWithClusterConfig("/root/install.sh", clusterConfig, awsCreds, _flagClusterEnv)
162+
out, exitCode, err := runManagerWithClusterConfig("/root/install.sh", clusterConfig, awsCreds, _flagClusterEnv, nil, nil)
162163
if err != nil {
163164
if clusterConfig.APIGatewaySetting == clusterconfig.PublicAPIGatewaySetting {
164165
awsClient.DeleteAPIGatewayByTag(clusterconfig.ClusterNameTag, clusterConfig.ClusterName) // best effort deletion
@@ -238,6 +239,30 @@ var _upCmd = &cobra.Command{
238239
exit.Error(ErrorClusterUp(out + helpStr))
239240
}
240241

242+
loadBalancer, err := awsClient.FindLoadBalancer(map[string]string{
243+
clusterconfig.ClusterNameTag: clusterConfig.ClusterName,
244+
"cortex.dev/load-balancer": "operator",
245+
})
246+
if err != nil {
247+
exit.Error(errors.Append(err, fmt.Sprintf("\n\nunable to locate operator load balancer; you can attempt to resolve this issue and configure your CLI environment by running `cortex cluster info --env %s`", _flagClusterEnv)))
248+
}
249+
if loadBalancer == nil {
250+
exit.Error(ErrorNoOperatorLoadBalancer(_flagClusterEnv))
251+
}
252+
253+
newEnvironment := cliconfig.Environment{
254+
Name: _flagClusterEnv,
255+
Provider: types.AWSProviderType,
256+
OperatorEndpoint: pointer.String("https://" + *loadBalancer.DNSName),
257+
AWSAccessKeyID: pointer.String(awsCreds.CortexAWSAccessKeyID),
258+
AWSSecretAccessKey: pointer.String(awsCreds.CortexAWSSecretAccessKey),
259+
}
260+
261+
err = addEnvToCLIConfig(newEnvironment)
262+
if err != nil {
263+
exit.Error(errors.Append(err, fmt.Sprintf("unable to configure cli environment; you can attempt to resolve this issue and configure your CLI environment by running `cortex cluster info --env %s`", _flagClusterEnv)))
264+
}
265+
241266
fmt.Printf(console.Bold("\nan environment named \"%s\" has been configured for this cluster; append `--env %s` to cortex commands to connect to it (e.g. `cortex deploy --env %s`), or set it as your default with `cortex env default %s`\n"), _flagClusterEnv, _flagClusterEnv, _flagClusterEnv, _flagClusterEnv)
242267
},
243268
}
@@ -289,7 +314,7 @@ var _configureCmd = &cobra.Command{
289314
exit.Error(err)
290315
}
291316

292-
out, exitCode, err := runManagerWithClusterConfig("/root/install.sh --update", clusterConfig, awsCreds, _flagClusterEnv)
317+
out, exitCode, err := runManagerWithClusterConfig("/root/install.sh --update", clusterConfig, awsCreds, _flagClusterEnv, nil, nil)
293318
if err != nil {
294319
exit.Error(err)
295320
}
@@ -375,6 +400,12 @@ var _downCmd = &cobra.Command{
375400
}
376401
}
377402

403+
// updating CLI env is best-effort, so ignore errors
404+
loadBalancer, _ := awsClient.FindLoadBalancer(map[string]string{
405+
clusterconfig.ClusterNameTag: *accessConfig.ClusterName,
406+
"cortex.dev/load-balancer": "operator",
407+
})
408+
378409
if !_flagClusterDisallowPrompt {
379410
prompt.YesOrExit(fmt.Sprintf("your cluster named \"%s\" in %s will be spun down and all apis will be deleted, are you sure you want to continue?", *accessConfig.ClusterName, *accessConfig.Region), "", "")
380411
}
@@ -421,7 +452,7 @@ var _downCmd = &cobra.Command{
421452
}
422453

423454
fmt.Println("○ spinning down the cluster ...")
424-
out, exitCode, err := runManagerAccessCommand("/root/uninstall.sh", *accessConfig, awsCreds, _flagClusterEnv)
455+
out, exitCode, err := runManagerAccessCommand("/root/uninstall.sh", *accessConfig, awsCreds, _flagClusterEnv, nil, nil)
425456
if err != nil {
426457
exit.Error(err)
427458
}
@@ -431,8 +462,24 @@ var _downCmd = &cobra.Command{
431462
exit.Error(ErrorClusterDown(out + helpStr))
432463
}
433464

434-
cachedConfigPath := cachedClusterConfigPath(*accessConfig.ClusterName, *accessConfig.Region)
435-
os.Remove(cachedConfigPath)
465+
// best-effort deletion of cli environment(s)
466+
if loadBalancer != nil {
467+
envNames, isDefaultEnv, _ := getEnvNamesByOperatorEndpoint(*loadBalancer.DNSName)
468+
if len(envNames) > 0 {
469+
for _, envName := range envNames {
470+
removeEnvFromCLIConfig(envName)
471+
}
472+
fmt.Printf("✓ deleted the %s environment configuration%s\n", s.StrsAnd(envNames), s.SIfPlural(len(envNames)))
473+
if isDefaultEnv {
474+
fmt.Println("✓ set the default environment to local")
475+
}
476+
}
477+
}
478+
479+
fmt.Printf("\nplease check CloudFormation to ensure that all resources for the %s cluster eventually become successfully deleted: %s\n", *accessConfig.ClusterName, clusterstate.CloudFormationURL(*accessConfig.ClusterName, *accessConfig.Region))
480+
481+
cachedClusterConfigPath := cachedClusterConfigPath(*accessConfig.ClusterName, *accessConfig.Region)
482+
os.Remove(cachedClusterConfigPath)
436483
},
437484
}
438485

@@ -491,7 +538,7 @@ func cmdInfo(awsCreds AWSCredentials, accessConfig *clusterconfig.AccessConfig,
491538

492539
clusterConfig := refreshCachedClusterConfig(awsCreds, accessConfig, disallowPrompt)
493540

494-
out, exitCode, err := runManagerWithClusterConfig("/root/info.sh", &clusterConfig, awsCreds, _flagClusterEnv)
541+
out, exitCode, err := runManagerWithClusterConfig("/root/info.sh", &clusterConfig, awsCreds, _flagClusterEnv, nil, nil)
495542
if err != nil {
496543
exit.Error(err)
497544
}
@@ -724,36 +771,43 @@ func updateInfoEnvironment(operatorEndpoint string, awsCreds AWSCredentials, dis
724771
}
725772

726773
func cmdDebug(awsCreds AWSCredentials, accessConfig *clusterconfig.AccessConfig) {
727-
out, exitCode, err := runManagerAccessCommand("/root/debug.sh", *accessConfig, awsCreds, _flagClusterEnv)
774+
// note: if modifying this string, also change it in files.IgnoreCortexDebug()
775+
debugFileName := fmt.Sprintf("cortex-debug-%s.tgz", time.Now().UTC().Format("2006-01-02-15-04-05"))
776+
777+
containerDebugPath := "/out/" + debugFileName
778+
copyFromPaths := []dockerCopyFromPath{
779+
{
780+
containerPath: containerDebugPath,
781+
localDir: _cwd,
782+
},
783+
}
784+
785+
out, exitCode, err := runManagerAccessCommand("/root/debug.sh "+containerDebugPath, *accessConfig, awsCreds, _flagClusterEnv, nil, copyFromPaths)
728786
if err != nil {
729787
exit.Error(err)
730788
}
731789
if exitCode == nil || *exitCode != 0 {
732790
exit.Error(ErrorClusterDebug(out))
733791
}
734792

735-
timestamp := time.Now().UTC().Format("2006-01-02-15-04-05")
736-
userDebugPath := fmt.Sprintf("cortex-debug-%s.tgz", timestamp) // note: if modifying this string, also change it in files.IgnoreCortexDebug()
737-
err = os.Rename(_debugPath, userDebugPath)
738-
if err != nil {
739-
exit.Error(errors.WithStack(err))
740-
}
741-
742-
fmt.Println("saved cluster info to ./" + userDebugPath)
793+
fmt.Println("saved cluster info to ./" + debugFileName)
743794
return
744795
}
745796

746797
func refreshCachedClusterConfig(awsCreds AWSCredentials, accessConfig *clusterconfig.AccessConfig, disallowPrompt bool) clusterconfig.Config {
747798
// add empty file if cached cluster doesn't exist so that the file output by manager container maintains current user permissions
748-
cachedConfigPath := cachedClusterConfigPath(*accessConfig.ClusterName, *accessConfig.Region)
749-
if !files.IsFile(cachedConfigPath) {
750-
files.MakeEmptyFile(cachedConfigPath)
751-
}
799+
cachedClusterConfigPath := cachedClusterConfigPath(*accessConfig.ClusterName, *accessConfig.Region)
800+
containerConfigPath := fmt.Sprintf("/out/%s", filepath.Base(cachedClusterConfigPath))
752801

753-
mountedConfigPath := mountedClusterConfigPath(*accessConfig.ClusterName, *accessConfig.Region)
802+
copyFromPaths := []dockerCopyFromPath{
803+
{
804+
containerPath: containerConfigPath,
805+
localDir: files.Dir(cachedClusterConfigPath),
806+
},
807+
}
754808

755809
fmt.Print("syncing cluster configuration ...\n\n")
756-
out, exitCode, err := runManagerAccessCommand("/root/refresh.sh "+mountedConfigPath, *accessConfig, awsCreds, _flagClusterEnv)
810+
out, exitCode, err := runManagerAccessCommand("/root/refresh.sh "+containerConfigPath, *accessConfig, awsCreds, _flagClusterEnv, nil, copyFromPaths)
757811
if err != nil {
758812
exit.Error(err)
759813
}
@@ -762,7 +816,7 @@ func refreshCachedClusterConfig(awsCreds AWSCredentials, accessConfig *clusterco
762816
}
763817

764818
refreshedClusterConfig := &clusterconfig.Config{}
765-
readCachedClusterConfigFile(refreshedClusterConfig, cachedConfigPath)
819+
readCachedClusterConfigFile(refreshedClusterConfig, cachedClusterConfigPath)
766820
return *refreshedClusterConfig
767821
}
768822

cli/cmd/deploy.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"github.com/cortexlabs/cortex/cli/cluster"
2525
"github.com/cortexlabs/cortex/cli/local"
2626
"github.com/cortexlabs/cortex/cli/types/flags"
27+
"github.com/cortexlabs/cortex/pkg/lib/archive"
2728
"github.com/cortexlabs/cortex/pkg/lib/errors"
2829
"github.com/cortexlabs/cortex/pkg/lib/exit"
2930
"github.com/cortexlabs/cortex/pkg/lib/files"
@@ -34,7 +35,6 @@ import (
3435
s "github.com/cortexlabs/cortex/pkg/lib/strings"
3536
"github.com/cortexlabs/cortex/pkg/lib/table"
3637
"github.com/cortexlabs/cortex/pkg/lib/telemetry"
37-
"github.com/cortexlabs/cortex/pkg/lib/zip"
3838
"github.com/cortexlabs/cortex/pkg/operator/schema"
3939
"github.com/cortexlabs/cortex/pkg/types"
4040
"github.com/cortexlabs/cortex/pkg/types/userconfig"
@@ -219,8 +219,8 @@ func getDeploymentBytes(provider types.ProviderType, configPath string) (map[str
219219
didPromptFileCount = true
220220
}
221221

222-
projectZipBytes, err := zip.ToMem(&zip.Input{
223-
FileLists: []zip.FileListInput{
222+
projectZipBytes, _, err := archive.ZipToMem(&archive.Input{
223+
FileLists: []archive.FileListInput{
224224
{
225225
Sources: projectPaths,
226226
RemovePrefix: projectRoot,

cli/cmd/errors.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ const (
4949
ErrOperatorConfigFromLocalEnvironment = "cli.operater_config_from_local_environment"
5050
ErrFieldNotFoundInEnvironment = "cli.field_not_found_in_environment"
5151
ErrInvalidOperatorEndpoint = "cli.invalid_operator_endpoint"
52+
ErrNoOperatorLoadBalancer = "cli.no_operator_load_balancer"
5253
ErrCortexYAMLNotFound = "cli.cortex_yaml_not_found"
5354
ErrConnectToDockerDaemon = "cli.connect_to_docker_daemon"
5455
ErrDockerPermissions = "cli.docker_permissions"
@@ -130,6 +131,14 @@ func ErrorInvalidOperatorEndpoint(endpoint string) error {
130131
})
131132
}
132133

134+
// err can be passed in as nil
135+
func ErrorNoOperatorLoadBalancer(envName string) error {
136+
return errors.WithStack(&errors.Error{
137+
Kind: ErrNoOperatorLoadBalancer,
138+
Message: fmt.Sprintf("unable to locate operator load balancer; you can attempt to resolve this issue and configure your CLI environment by running `cortex cluster info --env %s`", envName),
139+
})
140+
}
141+
133142
func ErrorCortexYAMLNotFound() error {
134143
return errors.WithStack(&errors.Error{
135144
Kind: ErrCortexYAMLNotFound,

cli/cmd/lib_cli_config.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -890,6 +890,28 @@ func removeEnvFromCLIConfig(envName string) error {
890890
return nil
891891
}
892892

893+
// returns the list of environment names, and whether any of them were the default
894+
func getEnvNamesByOperatorEndpoint(operatorEndpoint string) ([]string, bool, error) {
895+
cliConfig, err := readCLIConfig()
896+
if err != nil {
897+
return nil, false, err
898+
}
899+
900+
var envNames []string
901+
isDefaultEnv := false
902+
903+
for _, env := range cliConfig.Environments {
904+
if env.OperatorEndpoint != nil && s.LastSplit(*env.OperatorEndpoint, "//") == s.LastSplit(operatorEndpoint, "//") {
905+
envNames = append(envNames, env.Name)
906+
if env.Name == cliConfig.DefaultEnvironment {
907+
isDefaultEnv = true
908+
}
909+
}
910+
}
911+
912+
return envNames, isDefaultEnv, nil
913+
}
914+
893915
func readCLIConfig() (cliconfig.CLIConfig, error) {
894916
if _cachedCLIConfig != nil {
895917
return *_cachedCLIConfig, nil

cli/cmd/lib_cluster_config.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,6 @@ func cachedClusterConfigPath(clusterName string, region string) string {
4242
return filepath.Join(_localDir, fmt.Sprintf("cluster_%s_%s.yaml", clusterName, region))
4343
}
4444

45-
func mountedClusterConfigPath(clusterName string, region string) string {
46-
return filepath.Join("/.cortex", fmt.Sprintf("cluster_%s_%s.yaml", clusterName, region))
47-
}
48-
4945
func existingCachedClusterConfigPaths() []string {
5046
paths, err := files.ListDir(_localDir, false)
5147
if err != nil {

0 commit comments

Comments
 (0)