From cd6749da4d9df0daa2c48480b2d87b4be24cbf28 Mon Sep 17 00:00:00 2001 From: Adam Ross Date: Wed, 16 Aug 2017 20:18:02 -0700 Subject: [PATCH 1/6] Add checks for rig dependencies and harden environment and error handling of disk usage checks. --- cli/commands/doctor.go | 71 ++++++++++++++++++++++++++++++------------ 1 file changed, 51 insertions(+), 20 deletions(-) diff --git a/cli/commands/doctor.go b/cli/commands/doctor.go index 2cbe153..0ea4bfb 100644 --- a/cli/commands/doctor.go +++ b/cli/commands/doctor.go @@ -29,6 +29,25 @@ func (cmd *Doctor) Commands() []cli.Command { } func (cmd *Doctor) Run(c *cli.Context) error { + // 0. Ensure all of rig's dependencies are available in the PATH. + if err := exec.Command("docker", "-h").Start(); err == nil { + cmd.out.Info.Println("Docker is installed."); + } else { + cmd.out.Error.Fatal("Docker (docker) is not installed."); + } + if runtime.GOOS != "linux" { + if err := exec.Command("docker-machine", "-h").Start(); err == nil { + cmd.out.Info.Println("Docker Machine is installed."); + } else { + cmd.out.Error.Fatal("Docker Machine (docker-machine) is not installed."); + } + } + if err := exec.Command("docker-compose", "-h").Start(); err == nil { + cmd.out.Info.Println("Docker Compose is installed."); + } else { + cmd.out.Warning.Printf("Docker Compose (docker-compose) is not installed."); + } + // 1. Ensure the configured docker-machine matches the set environment. if cmd.machine.Exists() { if _, isset := os.LookupEnv("DOCKER_MACHINE_NAME"); isset == false { @@ -111,33 +130,45 @@ func (cmd *Doctor) Run(c *cli.Context) error { } // 5. Check for storage on VM volume - output, err := exec.Command("docker-machine", "ssh", cmd.machine.Name, "df -h 2> /dev/null | grep /dev/sda1 | head -1 | awk '{print $5}' | sed 's/%//'").Output() - dataUsage := strings.TrimSpace(string(output)) - if i, err := strconv.Atoi(dataUsage); err == nil { - if i >= 85 && i < 95 { - cmd.out.Warning.Printf("Data volume (/data) is %d%% used. Please free up space soon.", i) - } else if i >= 95 { - cmd.out.Error.Printf("Data volume (/data) is %d%% used. Please free up space. Try 'docker system prune' or removing old projects / databases from /data.", i) + if runtime.GOOS != "linux" { + output, err := exec.Command("docker-machine", "ssh", cmd.machine.Name, "df -h 2> /dev/null | grep /dev/sda1 | head -1 | awk '{print $5}' | sed 's/%//'").Output() + if err == nil { + dataUsage := strings.TrimSpace(string(output)) + if i, err := strconv.Atoi(dataUsage); err == nil { + if i >= 85 && i < 95 { + cmd.out.Warning.Printf("Data volume (/data) is %d%% used. Please free up space soon.", i) + } else if i >= 95 { + cmd.out.Error.Printf("Data volume (/data) is %d%% used. Please free up space. Try 'docker system prune' or removing old projects / databases from /data.", i) + } else { + cmd.out.Info.Printf("Data volume (/data) is %d%% used.", i) + } + } else { + cmd.out.Warning.Printf("Unable to determine usage level of /data volume. Failed to parse '%s'", dataUsage) + } } else { - cmd.out.Info.Printf("Data volume (/data) is %d%% used.", i) + cmd.out.Warning.Printf("Unable to determine usage level of /data volume. Failed to execute 'df': %v", err); } - } else { - cmd.out.Warning.Printf("Unable to determine usage level of /data volume. Failed to parse '%s'", dataUsage) } // 6. Check for storage on /Users - output, err = exec.Command("docker-machine", "ssh", cmd.machine.Name, "df -h 2> /dev/null | grep /Users | head -1 | awk '{print $5}' | sed 's/%//'").Output() - userUsage := strings.TrimSpace(string(output)) - if i, err := strconv.Atoi(userUsage); err == nil { - if i >= 85 && i < 95 { - cmd.out.Warning.Printf("Root drive (/Users) is %d%% used. Please free up space soon.", i) - } else if i >= 95 { - cmd.out.Error.Printf("Root drive (/Users) is %d%% used. Please free up space.", i) + if runtime.GOOS != "linux" { + output, err := exec.Command("docker-machine", "ssh", cmd.machine.Name, "df -h 2> /dev/null | grep /Users | head -1 | awk '{print $5}' | sed 's/%//'").Output() + if err == nil { + userUsage := strings.TrimSpace(string(output)) + if i, err := strconv.Atoi(userUsage); err == nil { + if i >= 85 && i < 95 { + cmd.out.Warning.Printf("Root drive (/Users) is %d%% used. Please free up space soon.", i) + } else if i >= 95 { + cmd.out.Error.Printf("Root drive (/Users) is %d%% used. Please free up space.", i) + } else { + cmd.out.Info.Printf("Root drive (/Users) is %d%% used.", i) + } + } else { + cmd.out.Warning.Printf("Unable to determine usage level of root drive (/Users). Failed to parse '%s'", userUsage) + } } else { - cmd.out.Info.Printf("Root drive (/Users) is %d%% used.", i) + cmd.out.Warning.Printf("Unable to determine usage level of root drive (/Users). Failed to execute 'df': %v", err); } - } else { - cmd.out.Warning.Printf("Unable to determine usage level of root drive (/Users). Failed to parse '%s'", userUsage) } return nil From 55747ebe838a158353a06d312cfa4fc964909bf5 Mon Sep 17 00:00:00 2001 From: Adam Ross Date: Wed, 16 Aug 2017 20:21:48 -0700 Subject: [PATCH 2/6] Fix up formatting standards. --- cli/commands/doctor.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/cli/commands/doctor.go b/cli/commands/doctor.go index 0ea4bfb..6ce7fb7 100644 --- a/cli/commands/doctor.go +++ b/cli/commands/doctor.go @@ -31,21 +31,21 @@ func (cmd *Doctor) Commands() []cli.Command { func (cmd *Doctor) Run(c *cli.Context) error { // 0. Ensure all of rig's dependencies are available in the PATH. if err := exec.Command("docker", "-h").Start(); err == nil { - cmd.out.Info.Println("Docker is installed."); + cmd.out.Info.Println("Docker is installed.") } else { - cmd.out.Error.Fatal("Docker (docker) is not installed."); + cmd.out.Error.Fatal("Docker (docker) is not installed.") } if runtime.GOOS != "linux" { if err := exec.Command("docker-machine", "-h").Start(); err == nil { - cmd.out.Info.Println("Docker Machine is installed."); + cmd.out.Info.Println("Docker Machine is installed.") } else { - cmd.out.Error.Fatal("Docker Machine (docker-machine) is not installed."); + cmd.out.Error.Fatal("Docker Machine (docker-machine) is not installed.") } } if err := exec.Command("docker-compose", "-h").Start(); err == nil { - cmd.out.Info.Println("Docker Compose is installed."); + cmd.out.Info.Println("Docker Compose is installed.") } else { - cmd.out.Warning.Printf("Docker Compose (docker-compose) is not installed."); + cmd.out.Warning.Printf("Docker Compose (docker-compose) is not installed.") } // 1. Ensure the configured docker-machine matches the set environment. @@ -130,7 +130,7 @@ func (cmd *Doctor) Run(c *cli.Context) error { } // 5. Check for storage on VM volume - if runtime.GOOS != "linux" { + if runtime.GOOS != "linux" { output, err := exec.Command("docker-machine", "ssh", cmd.machine.Name, "df -h 2> /dev/null | grep /dev/sda1 | head -1 | awk '{print $5}' | sed 's/%//'").Output() if err == nil { dataUsage := strings.TrimSpace(string(output)) @@ -146,7 +146,7 @@ func (cmd *Doctor) Run(c *cli.Context) error { cmd.out.Warning.Printf("Unable to determine usage level of /data volume. Failed to parse '%s'", dataUsage) } } else { - cmd.out.Warning.Printf("Unable to determine usage level of /data volume. Failed to execute 'df': %v", err); + cmd.out.Warning.Printf("Unable to determine usage level of /data volume. Failed to execute 'df': %v", err) } } @@ -167,7 +167,7 @@ func (cmd *Doctor) Run(c *cli.Context) error { cmd.out.Warning.Printf("Unable to determine usage level of root drive (/Users). Failed to parse '%s'", userUsage) } } else { - cmd.out.Warning.Printf("Unable to determine usage level of root drive (/Users). Failed to execute 'df': %v", err); + cmd.out.Warning.Printf("Unable to determine usage level of root drive (/Users). Failed to execute 'df': %v", err) } } From 871a81a5d426d31d398fdf446ce76cf23411ad64 Mon Sep 17 00:00:00 2001 From: Adam Ross Date: Thu, 17 Aug 2017 21:38:37 -0700 Subject: [PATCH 3/6] Add support for outrigger.yml in addition to .outrigger.yml. --- cli/commands/project.go | 2 +- cli/commands/project_config.go | 26 +++++++++++++++++++++----- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/cli/commands/project.go b/cli/commands/project.go index d0036be..0d66eeb 100644 --- a/cli/commands/project.go +++ b/cli/commands/project.go @@ -23,7 +23,7 @@ func (cmd *Project) Commands() []cli.Command { command := cli.Command{ Name: "project", Usage: "Run project-specific commands.", - Description: "Run project-specific commands as part of development.\n\n\tConfigured scripts are driven by an Outrigger configuration file expected at your project root directory.\n\n\tBy default, this is a YAML file named '.outrigger.yml'. It can be overridden by setting an environment variable $RIG_PROJECT_CONFIG_FILE.", + Description: "Run project-specific commands as part of development.\n\n\tConfigured scripts are driven by an Outrigger configuration file expected at your project root directory.\n\n\tBy default, this is a YAML file named 'outrigger.yml' with fallback to '.outrigger.yml'. It can be overridden by setting an environment variable $RIG_PROJECT_CONFIG_FILE.", Aliases: []string{"run"}, Category: "Development", Before: cmd.Before, diff --git a/cli/commands/project_config.go b/cli/commands/project_config.go index cec1a19..9fbf857 100644 --- a/cli/commands/project_config.go +++ b/cli/commands/project_config.go @@ -36,14 +36,30 @@ type ProjectConfig struct { // Create a new ProjectConfig using configured or default locations func NewProjectConfig() *ProjectConfig { projectConfigFile := os.Getenv("RIG_PROJECT_CONFIG_FILE") + + var discovery []string if projectConfigFile == "" { - projectConfigFile = "./.outrigger.yml" + discovery = make([]string, 2) + discovery[0] = "./outrigger.yml" + discovery[1] = "./.outrigger.yml" + } else { + discovery = make([]string, 1) + discovery[0] = projectConfigFile } - return NewProjectConfigFromFile(projectConfigFile) + + readyConfig := &ProjectConfig{} + for _, filePath := range discovery { + if config, err := NewProjectConfigFromFile(filePath); err == nil { + readyConfig = config + break + } + } + + return readyConfig } // Create a new ProjectConfig from the specified file -func NewProjectConfigFromFile(filename string) *ProjectConfig { +func NewProjectConfigFromFile(filename string) (*ProjectConfig, error) { logger := util.Logger() filepath, _ := filepath.Abs(filename) @@ -55,7 +71,7 @@ func NewProjectConfigFromFile(filename string) *ProjectConfig { yamlFile, err := ioutil.ReadFile(config.File) if err != nil { logger.Verbose.Printf("No project configuration file found at: %s", config.File) - return config + return config, err } if err := yaml.Unmarshal(yamlFile, config); err != nil { @@ -76,7 +92,7 @@ func NewProjectConfigFromFile(filename string) *ProjectConfig { } } - return config + return config, nil } // Ensures our configuration data structure conforms to our ad hoc schema. From 99572536e1dc626e027686f7d27b1891c5cf4bf7 Mon Sep 17 00:00:00 2001 From: Adam Ross Date: Tue, 10 Oct 2017 11:16:41 -0700 Subject: [PATCH 4/6] Do not compare client/server Docker versions on Linux. (#75) --- cli/commands/doctor.go | 45 +++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/cli/commands/doctor.go b/cli/commands/doctor.go index 6ce7fb7..6195621 100644 --- a/cli/commands/doctor.go +++ b/cli/commands/doctor.go @@ -70,29 +70,34 @@ func (cmd *Doctor) Run(c *cli.Context) error { } // 2. Check Docker API Version compatibility - clientApiVersion := util.GetDockerClientApiVersion() - serverApiVersion, err := util.GetDockerServerApiVersion(cmd.machine.Name) - serverMinApiVersion, _ := util.GetDockerServerMinApiVersion(cmd.machine.Name) + if runtime.GOOS != "linux" { + clientApiVersion := util.GetDockerClientApiVersion() + serverApiVersion, err := util.GetDockerServerApiVersion(cmd.machine.Name) + serverMinApiVersion, _ := util.GetDockerServerMinApiVersion(cmd.machine.Name) - // Older clients can talk to newer servers, and when you ask a newer server - // it's version in the presence of an older server it will downgrade it's - // compatability as far as possible. So as long as the client API is not greater - // than the servers current version or less than the servers minimum api version - // then we are compatible - constraintString := fmt.Sprintf("<= %s", serverApiVersion) - if serverMinApiVersion != nil { - constraintString = fmt.Sprintf(">= %s", serverMinApiVersion) - } - apiConstraint, _ := version.NewConstraint(constraintString) + // Older clients can talk to newer servers, and when you ask a newer server + // it's version in the presence of an older server it will downgrade it's + // compatability as far as possible. So as long as the client API is not greater + // than the servers current version or less than the servers minimum api version + // then we are compatible + constraintString := fmt.Sprintf("<= %s", serverApiVersion) + if serverMinApiVersion != nil { + constraintString = fmt.Sprintf(">= %s", serverMinApiVersion) + } + apiConstraint, _ := version.NewConstraint(constraintString) - if err != nil { - cmd.out.Error.Println("Could not determine Docker Machine Docker versions: ", err) - } else if clientApiVersion.Equal(serverApiVersion) { - cmd.out.Info.Printf("Docker Client (%s) and Server (%s) have equal API Versions", clientApiVersion, serverApiVersion) - } else if apiConstraint.Check(clientApiVersion) { - cmd.out.Info.Printf("Docker Client (%s) has Server compatible API version (%s). Server current (%s), Server min compat (%s)", clientApiVersion, constraintString, serverApiVersion, serverMinApiVersion) + if err != nil { + cmd.out.Error.Println("Could not determine Docker Machine Docker versions: ", err) + } else if clientApiVersion.Equal(serverApiVersion) { + cmd.out.Info.Printf("Docker Client (%s) and Server (%s) have equal API Versions", clientApiVersion, serverApiVersion) + } else if apiConstraint.Check(clientApiVersion) { + cmd.out.Info.Printf("Docker Client (%s) has Server compatible API version (%s). Server current (%s), Server min compat (%s)", clientApiVersion, constraintString, serverApiVersion, serverMinApiVersion) + } else { + cmd.out.Error.Printf("Docker Client (%s) is incompatible with Server. Server current (%s), Server min compat (%s). Use `rig upgrade` to fix this.", clientApiVersion, serverApiVersion, serverMinApiVersion) + } } else { - cmd.out.Error.Printf("Docker Client (%s) is incompatible with Server. Server current (%s), Server min compat (%s). Use `rig upgrade` to fix this.", clientApiVersion, serverApiVersion, serverMinApiVersion) + dockerApiVersion := util.GetDockerClientApiVersion() + cmd.out.Info.Printf("Docker Version: %s", dockerApiVersion) } // 3. Pull down the data from DNSDock. This will confirm we can resolve names as well From db7ed4c7d7c228c4ecacba0a867c3e20fb541b6e Mon Sep 17 00:00:00 2001 From: Frank Febbraro Date: Tue, 10 Oct 2017 15:53:24 -0700 Subject: [PATCH 5/6] Add linux bind volume support (#73) * added linux bind volume support * go fmt fixes * rebuid the bind volume every time (in case the absolute path has changed) * Do not compare client/server Docker versions on Linux. (#75) * added linux bind volume support * go fmt fixes * rebuid the bind volume every time (in case the absolute path has changed) * Updated for better doctor/linux compat * refactored to handle linux sync volume and default windows/mac to unison sync --- cli/commands/doctor.go | 64 +++++++++++++++++------------------- cli/commands/project_sync.go | 50 ++++++++++++++++++++++++---- 2 files changed, 74 insertions(+), 40 deletions(-) diff --git a/cli/commands/doctor.go b/cli/commands/doctor.go index 6195621..20c0320 100644 --- a/cli/commands/doctor.go +++ b/cli/commands/doctor.go @@ -49,24 +49,26 @@ func (cmd *Doctor) Run(c *cli.Context) error { } // 1. Ensure the configured docker-machine matches the set environment. - if cmd.machine.Exists() { - if _, isset := os.LookupEnv("DOCKER_MACHINE_NAME"); isset == false { - cmd.out.Error.Fatalf("Docker configuration is not set. Please run 'eval \"$(rig config)\"'.") - } else if cmd.machine.Name != os.Getenv("DOCKER_MACHINE_NAME") { - cmd.out.Error.Fatalf("Your environment configuration specifies a different machine. Please re-run as 'rig --name=\"%s\" doctor'.", cmd.machine.Name) - } else { - cmd.out.Info.Printf("Docker Machine (%s) name matches your environment configuration.", cmd.machine.Name) - } - if output, err := exec.Command("docker-machine", "url", cmd.machine.Name).Output(); err == nil { - hostUrl := strings.TrimSpace(string(output)) - if hostUrl != os.Getenv("DOCKER_HOST") { - cmd.out.Error.Fatalf("Docker Host configuration should be '%s' but got '%s'. Please re-run 'eval \"$(rig config)\"'.", os.Getenv("DOCKER_HOST"), hostUrl) + if runtime.GOOS != "linux" { + if cmd.machine.Exists() { + if _, isset := os.LookupEnv("DOCKER_MACHINE_NAME"); isset == false { + cmd.out.Error.Fatalf("Docker configuration is not set. Please run 'eval \"$(rig config)\"'.") + } else if cmd.machine.Name != os.Getenv("DOCKER_MACHINE_NAME") { + cmd.out.Error.Fatalf("Your environment configuration specifies a different machine. Please re-run as 'rig --name=\"%s\" doctor'.", cmd.machine.Name) } else { - cmd.out.Info.Printf("Docker Machine (%s) URL (%s) matches your environment configuration.", cmd.machine.Name, hostUrl) + cmd.out.Info.Printf("Docker Machine (%s) name matches your environment configuration.", cmd.machine.Name) + } + if output, err := exec.Command("docker-machine", "url", cmd.machine.Name).Output(); err == nil { + hostUrl := strings.TrimSpace(string(output)) + if hostUrl != os.Getenv("DOCKER_HOST") { + cmd.out.Error.Fatalf("Docker Host configuration should be '%s' but got '%s'. Please re-run 'eval \"$(rig config)\"'.", os.Getenv("DOCKER_HOST"), hostUrl) + } else { + cmd.out.Info.Printf("Docker Machine (%s) URL (%s) matches your environment configuration.", cmd.machine.Name, hostUrl) + } } + } else { + cmd.out.Error.Fatalf("No machine named '%s' exists. Did you run 'rig start --name=\"%s\"'?", cmd.machine.Name, cmd.machine.Name) } - } else { - cmd.out.Error.Fatalf("No machine named '%s' exists. Did you run 'rig start --name=\"%s\"'?", cmd.machine.Name, cmd.machine.Name) } // 2. Check Docker API Version compatibility @@ -97,32 +99,28 @@ func (cmd *Doctor) Run(c *cli.Context) error { } } else { dockerApiVersion := util.GetDockerClientApiVersion() - cmd.out.Info.Printf("Docker Version: %s", dockerApiVersion) + cmd.out.Info.Printf("Docker API Version: %s", dockerApiVersion) } // 3. Pull down the data from DNSDock. This will confirm we can resolve names as well // as route to the appropriate IP addresses via the added route commands - if cmd.machine.IsRunning() { - dnsRecords := DnsRecords{BaseCommand{machine: cmd.machine, out: cmd.out}} - if records, err := dnsRecords.LoadRecords(); err == nil { - resolved := false - for _, record := range records { - if record["Name"] == "dnsdock" { - resolved = true - cmd.out.Info.Printf("DNS and routing services are working. DNSDock resolves to %s", record["IPs"]) - break - } + dnsRecords := DnsRecords{BaseCommand{machine: cmd.machine, out: cmd.out}} + if records, err := dnsRecords.LoadRecords(); err == nil { + resolved := false + for _, record := range records { + if record["Name"] == "dnsdock" { + resolved = true + cmd.out.Info.Printf("DNS and routing services are working. DNSDock resolves to %s", record["IPs"]) + break } + } - if !resolved { - cmd.out.Error.Println("Unable to verify DNS services are working.") - } - } else { - cmd.out.Error.Println("Unable to verify DNS services and routing are working.") - cmd.out.Error.Println(err) + if !resolved { + cmd.out.Error.Println("Unable to verify DNS services are working.") } } else { - cmd.out.Warning.Printf("Docker Machine `%s` is not running. Cannot determine if DNS resolution is working correctly.", cmd.machine.Name) + cmd.out.Error.Println("Unable to verify DNS services and routing are working.") + cmd.out.Error.Println(err) } // 4. Ensure that docker-machine-nfs script is available for our NFS mounts (Mac ONLY) diff --git a/cli/commands/project_sync.go b/cli/commands/project_sync.go index 6d668d1..1eece84 100644 --- a/cli/commands/project_sync.go +++ b/cli/commands/project_sync.go @@ -8,6 +8,7 @@ import ( "os/exec" "path" "regexp" + "runtime" "strings" "time" @@ -43,7 +44,7 @@ func (cmd *ProjectSync) Commands() []cli.Command { cli.IntFlag{ Name: "initial-sync-timeout", Value: 60, - Usage: "Maximum amount of time in seconds to allow for detecting each of start of the unison container and start of initial sync", + Usage: "Maximum amount of time in seconds to allow for detecting each of start of the unison container and start of initial sync. (not needed on linux)", EnvVar: "RIG_PROJECT_SYNC_TIMEOUT", }, // Arbitrary sleep length but anything less than 3 wasn't catching @@ -51,7 +52,7 @@ func (cmd *ProjectSync) Commands() []cli.Command { cli.IntFlag{ Name: "initial-sync-wait", Value: 5, - Usage: "Time in seconds to wait between checks to see if initial sync has finished.", + Usage: "Time in seconds to wait between checks to see if initial sync has finished. (not needed on linux)", EnvVar: "RIG_PROJECT_INITIAL_SYNC_WAIT", }, }, @@ -74,8 +75,21 @@ func (cmd *ProjectSync) Commands() []cli.Command { func (cmd *ProjectSync) RunStart(ctx *cli.Context) error { config := NewProjectConfig() volumeName := cmd.GetVolumeName(ctx, config) - cmd.out.Verbose.Printf("Starting sync with volume: %s", volumeName) + switch platform := runtime.GOOS; platform { + case "linux": + cmd.out.Verbose.Printf("Setting up local volume: %s", volumeName) + cmd.SetupBindVolume(volumeName) + default: + cmd.out.Verbose.Printf("Starting sync with volume: %s", volumeName) + cmd.StartUnisonSync(ctx, volumeName, config) + } + + return nil +} + +// For systems that need/support Unison +func (cmd *ProjectSync) StartUnisonSync(ctx *cli.Context, volumeName string, config *ProjectConfig) { // Ensure the processes can handle a large number of watches if err := cmd.machine.SetSysctl("fs.inotify.max_user_watches", MAX_WATCHES); err != nil { cmd.out.Error.Fatalf("Error configuring file watches on Docker Machine: %v", err) @@ -86,6 +100,7 @@ func (cmd *ProjectSync) RunStart(ctx *cli.Context) error { cmd.out.Info.Println("Starting unison container") unisonMinorVersion := cmd.GetUnisonMinorVersion() + cmd.out.Verbose.Printf("Local unison version for compatibilty: %s", unisonMinorVersion) exec.Command("docker", "container", "stop", volumeName).Run() err := exec.Command("docker", "container", "run", "--detach", "--rm", @@ -96,6 +111,7 @@ func (cmd *ProjectSync) RunStart(ctx *cli.Context) error { "--name", volumeName, fmt.Sprintf("outrigger/unison:%s", unisonMinorVersion), ).Run() + if err != nil { cmd.out.Error.Fatalf("Error starting sync container %s: %v", volumeName, err) } @@ -123,19 +139,39 @@ func (cmd *ProjectSync) RunStart(ctx *cli.Context) error { unisonArgs = append(unisonArgs, "-ignore", ignore) } } - cmd.out.Verbose.Printf("Unison Args: %s", strings.Join(unisonArgs[:], " ")) if err = exec.Command("unison", unisonArgs...).Start(); err != nil { cmd.out.Error.Fatalf("Error starting local unison process: %v", err) } - cmd.WaitForSyncInit(logFile, ctx.Int("initial-sync-timeout"), ctx.Int("initial-sync-wait")) +} - return nil +// For systems that have native container/volume support +func (cmd *ProjectSync) SetupBindVolume(volumeName string) { + + cmd.out.Info.Printf("Starting local bind volume: %s", volumeName) + exec.Command("docker", "volume", "rm", volumeName).Run() + + if workingDir, err := os.Getwd(); err == nil { + volumeArgs := []string{ + "volume", "create", + "--opt", "type=none", + "--opt", fmt.Sprintf("device=%s", workingDir), + "--opt", "o=bind", + volumeName, + } + exec.Command("docker", volumeArgs...).Run() + } else { + cmd.out.Error.Fatalf("Error resolving the working directory for volume creation: %v", err) + } } -// Start the unison sync process func (cmd *ProjectSync) RunStop(ctx *cli.Context) error { + if runtime.GOOS == "linux" { + cmd.out.Info.Println("No unison container to stop, using local bind volume") + return nil + } + config := NewProjectConfig() volumeName := cmd.GetVolumeName(ctx, config) cmd.out.Verbose.Printf("Stopping sync with volume: %s", volumeName) From f76dd23b29a5e3314be988a3ac3adae3d66437a2 Mon Sep 17 00:00:00 2001 From: Frank Febbraro Date: Tue, 10 Oct 2017 15:59:21 -0700 Subject: [PATCH 6/6] bump for version 1.3.2 --- CHANGELOG.md | 6 ++++++ cli/main.go | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2629a49..197346e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 1.3.2 + + - Added support for outrigger.yml (non-hidden) + - Added Linux compatibility to `doctor` + - Added support for Linux local bind volumes (for parity with `sync:start`) + ## 1.3.1 - Don't start NFS if not on Darwin diff --git a/cli/main.go b/cli/main.go index 79ba54f..f5ccd5d 100644 --- a/cli/main.go +++ b/cli/main.go @@ -8,7 +8,7 @@ import ( "github.com/urfave/cli" ) -const VERSION = "1.3.1" +const VERSION = "1.3.2" // It all starts here func main() {