devbox_launcher 0.3.0 → 0.3.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2b3edb043751826ec3d3dfec5c5cbfe867cecd1da4938f5f5b7fee2401903387
4
- data.tar.gz: 51d6d27541b6933ab9f7e2eca6a3c1d74bcf455fd6a447dabb9dcfe09852abb7
3
+ metadata.gz: 0ec99b19a115672c4122d2c1b8827727d32d184fa9fee7328ab503b85529f3d9
4
+ data.tar.gz: 230126704d2e2d5cc7d8c9be29450ec35ccc9d716b605c2831696155f6889eca
5
5
  SHA512:
6
- metadata.gz: b213b9982c3c7ffbc16db6b2555e4ef1ed4ab7ff59a0a3e10bbd6a7c800ce60006615dedb2caae32353ea27331a9c89b97fc30b973b6e73bf85ba34d2c86bbae
7
- data.tar.gz: 0f6a627362ff12fb49e7f1f508ee374adaaff932ca248c8d88cfb3209ea28ec94521e1443b7144a66ea270fe896b53aeb740c042dea1134de2aa28ee568b70bb
6
+ metadata.gz: 0b770f908bb60e3108b5b99b8f83f008f5ca77f83be40349da8f283f95ce725b9edbac6a6dcc9439769ee2206ccc3d8ba35cec6b0458a879d8afcf2d97a4faab
7
+ data.tar.gz: 53ac5dfd4eaa3356b15bdb846bbc418b277758458381e2b9f903a2900f0685a2e1a051181aa5e4e165d75ee2003537c241f98a9392f2c6e42bba7533fd55be33
@@ -4,6 +4,26 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [0.3.5]
8
+ ### Fixed
9
+ - When running commands, also rescue from whitelist of exceptions, and retry
10
+
11
+ ## [0.3.4]
12
+ ### Added
13
+ - Rescue from `Errno::ECONNREFUSED` and retry
14
+
15
+ ## [0.3.3]
16
+ ### Fixed
17
+ - Support launching multiple boxes at the same time
18
+
19
+ ## [0.3.2]
20
+ ### Fixed
21
+ - Fix: add missing file
22
+
23
+ ## [0.3.1]
24
+ ### Fixed
25
+ - Recover when the devbox is in a shutdown cycle
26
+
7
27
  ## [0.3.0]
8
28
  ### Changed
9
29
  - Label sessions with devbox
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- devbox_launcher (0.3.0)
4
+ devbox_launcher (0.3.5)
5
5
  activesupport (~> 6.0)
6
6
  bcrypt_pbkdf (~> 1.0)
7
7
  ed25519 (~> 1.2)
@@ -14,24 +14,24 @@ PATH
14
14
  GEM
15
15
  remote: https://rubygems.org/
16
16
  specs:
17
- activesupport (6.0.2.1)
17
+ activesupport (6.0.3.4)
18
18
  concurrent-ruby (~> 1.0, >= 1.0.2)
19
19
  i18n (>= 0.7, < 2)
20
20
  minitest (~> 5.1)
21
21
  tzinfo (~> 1.1)
22
- zeitwerk (~> 2.2)
22
+ zeitwerk (~> 2.2, >= 2.2.2)
23
23
  bcrypt_pbkdf (1.0.1)
24
24
  byebug (11.0.1)
25
25
  coderay (1.1.2)
26
- concurrent-ruby (1.1.5)
26
+ concurrent-ruby (1.1.7)
27
27
  diff-lcs (1.3)
28
28
  ed25519 (1.2.4)
29
- i18n (1.8.2)
29
+ i18n (1.8.5)
30
30
  concurrent-ruby (~> 1.0)
31
31
  method_source (0.9.2)
32
- minitest (5.14.0)
32
+ minitest (5.14.2)
33
33
  net-ssh (5.2.0)
34
- os (1.0.1)
34
+ os (1.1.1)
35
35
  pry (0.12.2)
36
36
  coderay (~> 1.1.0)
37
37
  method_source (~> 0.9.0)
@@ -56,9 +56,9 @@ GEM
56
56
  ssh-config (0.1.3)
57
57
  thor (1.0.1)
58
58
  thread_safe (0.3.6)
59
- tzinfo (1.2.6)
59
+ tzinfo (1.2.8)
60
60
  thread_safe (~> 0.1)
61
- zeitwerk (2.2.2)
61
+ zeitwerk (2.4.1)
62
62
 
63
63
  PLATFORMS
64
64
  ruby
@@ -16,3 +16,6 @@ end
16
16
 
17
17
  require "devbox_launcher/cli"
18
18
  require "devbox_launcher/watchman"
19
+ require "devbox_launcher/models/description"
20
+ require "devbox_launcher/models/mutagen"
21
+ require "devbox_launcher/models/box"
@@ -0,0 +1,213 @@
1
+ module DevboxLauncher
2
+ class Box
3
+
4
+ WAIT_BOOT_RESCUED_EXCEPTIONS = [
5
+ Net::SSH::ConnectionTimeout,
6
+ Net::SSH::Disconnect,
7
+ Errno::ECONNRESET,
8
+ Errno::ETIMEDOUT,
9
+ Errno::ECONNREFUSED,
10
+ ]
11
+ WAIT_BOOT_IN_SECONDS = 10.freeze
12
+ DEFAULT_IDENTIFY_FILE_PATH = "~/.ssh/google_compute_engine".freeze
13
+ SSH_CONFIG_PATH = File.expand_path("~/.ssh/config").freeze
14
+ CONFIG_PATH = File.expand_path("~/.devbox_launcher.yml").freeze
15
+ CONFIG = YAML.load_file(CONFIG_PATH).freeze
16
+
17
+ attr_reader :account
18
+
19
+ def initialize(account)
20
+ @account = account
21
+ end
22
+
23
+ def start
24
+ start_stdout, start_stderr, start_status =
25
+ run_command(start_cmd)
26
+
27
+ set_ssh_config!(hostname, {
28
+ username: username,
29
+ ip: description.ip,
30
+ })
31
+
32
+ wait_boot
33
+
34
+ reset_mutagen_session(
35
+ mutagen_config: config[:mutagen],
36
+ hostname: hostname,
37
+ )
38
+ end
39
+
40
+ def start_cmd
41
+ args = {
42
+ project: config[:project],
43
+ account: account,
44
+ }.map do |(key, val)|
45
+ ["--#{key}", val].join("=")
46
+ end.join(" ")
47
+
48
+ [
49
+ "gcloud",
50
+ "compute",
51
+ "instances",
52
+ "start",
53
+ name,
54
+ args
55
+ ].join(" ")
56
+ end
57
+
58
+ def wait_boot(tries: 1)
59
+ Net::SSH.start(hostname, username, timeout: WAIT_BOOT_IN_SECONDS) do |ssh|
60
+ puts "[#{ssh.exec!('date').chomp}] Machine booted"
61
+ end
62
+ rescue *WAIT_BOOT_RESCUED_EXCEPTIONS
63
+ puts "Not booted. Waiting #{WAIT_BOOT_IN_SECONDS} seconds before trying again..."
64
+
65
+ sleep WAIT_BOOT_IN_SECONDS
66
+
67
+ description = describe(name)
68
+ if !description.running?
69
+ puts "Detected that the machine is not running " \
70
+ "(status is #{description.status}). Booting it..."
71
+ start_box name, username
72
+ end
73
+
74
+ wait_boot name, username, tries: tries+1
75
+ end
76
+
77
+ def description(reload: false)
78
+ return @description if !reload && @description
79
+
80
+ puts "Fetching box's description..."
81
+
82
+ describe_command = %Q(gcloud compute instances describe #{name})
83
+ describe_stdout, describe_stderr, describe_status =
84
+ run_command(describe_command)
85
+
86
+ if !describe_status.success?
87
+ msg = "Problem fetching the description of #{name}. "
88
+ msg += "Please ensure you can call `#{describe_command}`.\n"
89
+ msg += "Error:\n"
90
+ msg += describe_stderr
91
+ fail msg
92
+ end
93
+
94
+ @description = Description.new(describe_stdout)
95
+ end
96
+
97
+ def set_ssh_config!(hostname, username:, ip:)
98
+ FileUtils.touch(SSH_CONFIG_PATH)
99
+ config = ConfigFile.new
100
+ args = {
101
+ "HostName" => ip,
102
+ "User" => username,
103
+ "IdentityFile" => DEFAULT_IDENTIFY_FILE_PATH,
104
+ }
105
+ args.each do |key, value|
106
+ config.set(hostname, key, value)
107
+ end
108
+ config.save
109
+ end
110
+
111
+ def reset_mutagen_session
112
+ mutagen_config = config[:mutagen]
113
+ return if mutagen_config.nil?
114
+
115
+ alpha_dir = mutagen_config[:alpha]
116
+ beta_dir = mutagen_config[:beta]
117
+
118
+ return if alpha_dir.nil? || beta_dir.nil?
119
+
120
+ terminate_mutagen_session
121
+
122
+ create_mutagen_session(
123
+ alpha_dir: alpha_dir,
124
+ beta_dir: beta_dir,
125
+ hostname: hostname,
126
+ username: username,
127
+ )
128
+
129
+ if OS.linux?
130
+ watch_alpha(alpha_dir: alpha_dir, hostname: hostname)
131
+ end
132
+ end
133
+
134
+ def terminate_mutagen_session(username)
135
+ puts "Terminating mutagen session..."
136
+ terminate_mutagen_command =
137
+ %Q(mutagen terminate --label-selector=#{username})
138
+ terminate_mutagen_stdout,
139
+ terminate_mutagen_stderr,
140
+ terminate_mutagen_status =
141
+ run_command(terminate_mutagen_command)
142
+
143
+ if not terminate_mutagen_status.success?
144
+ # mutagen prints to stdout and stderr
145
+ msg = "Failed to terminate mutagen sessions: " \
146
+ "#{terminate_mutagen_stdout} -" \
147
+ "#{terminate_mutagen_stderr}"
148
+ fail msg
149
+ end
150
+ end
151
+
152
+ def create_mutagen_session(alpha_dir:, beta_dir:, hostname:, username:)
153
+ puts "Create mutagen session syncing local #{alpha_dir} " \
154
+ "with #{hostname} #{beta_dir}"
155
+
156
+ create_mutagen_command = [
157
+ "mutagen sync create",
158
+ alpha_dir,
159
+ "#{hostname}:#{beta_dir}",
160
+ "--label=#{username}",
161
+ ]
162
+ create_mutagen_command << "--watch-mode-alpha=no-watch" if OS.linux?
163
+
164
+ create_mutagen_stdout,
165
+ create_mutagen_stderr,
166
+ create_mutagen_status =
167
+ run_command(create_mutagen_command.join(" "))
168
+
169
+ if not create_mutagen_status.success?
170
+ # mutagen prints to stdout and stderr
171
+ msg = "Failed to create mutagen sessions: " \
172
+ "#{create_mutagen_stdout} -" \
173
+ "#{create_mutagen_stderr}"
174
+ fail msg
175
+ end
176
+ end
177
+
178
+ def watch_alpha(alpha_dir:, hostname:)
179
+ watchman = Watchman.new(dir: alpha_dir)
180
+ watchman.trigger("mutagen sync flush --label-selector=#{hostname}")
181
+ end
182
+
183
+ def name
184
+ @name ||= config[:box]
185
+ end
186
+
187
+ def hostname
188
+ [name, username, "devbox"].join("-")
189
+ end
190
+
191
+ def username
192
+ @username ||= account.gsub(/\W/, "_")
193
+ end
194
+
195
+ def config
196
+ return @config if @config
197
+
198
+ if not CONFIG.has_key?(account)
199
+ fail "No config in #{CONFIG_PATH} found for #{account}"
200
+ end
201
+
202
+ @config = CONFIG[account].with_indifferent_access
203
+ end
204
+
205
+ def run_command(command, tries: 0)
206
+ Open3.capture3(command)
207
+ rescue *WAIT_BOOT_RESCUED_EXCEPTIONS
208
+ sleep WAIT_BOOT_IN_SECONDS
209
+ run_command(command, tries+1)
210
+ end
211
+
212
+ end
213
+ end
@@ -6,164 +6,12 @@ module DevboxLauncher
6
6
  SSH_CONFIG_PATH = File.expand_path("~/.ssh/config").freeze
7
7
  CONFIG_PATH = File.expand_path("~/.devbox_launcher.yml").freeze
8
8
  CONFIG = YAML.load_file(CONFIG_PATH).freeze
9
- LABEL = "devbox".freeze
10
9
 
11
10
  desc "start configured box for account", "Start a devbox by account"
12
11
  option :mosh, type: :boolean, desc: "Mosh in"
13
12
 
14
13
  def start(account)
15
- if not CONFIG.has_key?(account)
16
- fail "No config in #{CONFIG_PATH} found for #{account}"
17
- end
18
-
19
- config = CONFIG[account].with_indifferent_access
20
-
21
- username = account.gsub(/\W/, "_")
22
-
23
- set_account_command = %Q(gcloud config set account #{account})
24
- set_account_stdout, set_account_stderr, set_account_status =
25
- Open3.capture3(set_account_command)
26
-
27
- set_project_command = %Q(gcloud config set project #{config[:project]})
28
- set_project_stdout, set_project_stderr, set_project_status =
29
- Open3.capture3(set_project_command)
30
-
31
- name = config[:box]
32
-
33
- start_command = %Q(gcloud compute instances start #{name})
34
- start_stdout, start_stderr, start_status = Open3.capture3(start_command)
35
-
36
- puts "Fetching IP..."
37
- describe_command = %Q(gcloud compute instances describe #{name})
38
- describe_stdout, describe_stderr, describe_status =
39
- Open3.capture3(describe_command)
40
-
41
- if !describe_status.success?
42
- msg = "Problem fetching the IP address. "
43
- msg += "Please ensure you can call `#{describe_command}`.\n"
44
- msg += "Error:\n"
45
- msg += describe_stderr
46
- fail msg
47
- end
48
-
49
- description = YAML.load(describe_stdout)
50
-
51
- ip = description["networkInterfaces"].first["accessConfigs"].
52
- find { |config| config["kind"] == "compute#accessConfig" }["natIP"]
53
-
54
- puts "IP: #{ip}"
55
-
56
- hostname = "#{name}-devbox"
57
-
58
- set_ssh_config!(hostname, {
59
- username: username,
60
- ip: ip,
61
- })
62
-
63
- wait_boot(hostname, username)
64
-
65
- reset_mutagen_session(
66
- mutagen_config: config[:mutagen],
67
- hostname: hostname,
68
- )
69
-
70
- if options[:mosh]
71
- mosh_command = %Q(mosh #{hostname})
72
- system(mosh_command)
73
- end
74
- end
75
-
76
- no_commands do
77
- def wait_boot(hostname, username)
78
- Net::SSH.start(hostname, username, timeout: WAIT_BOOT_IN_SECONDS) do |ssh|
79
- puts "[#{ssh.exec!('date').chomp}] Machine booted"
80
- end
81
- rescue Net::SSH::ConnectionTimeout, Net::SSH::Disconnect, Errno::ECONNRESET
82
- puts "Not booted. Waiting #{WAIT_BOOT_IN_SECONDS} seconds before trying again..."
83
- wait_boot hostname, username
84
- end
85
-
86
- def set_ssh_config!(hostname, username:, ip:)
87
- FileUtils.touch(SSH_CONFIG_PATH)
88
- config = ConfigFile.new
89
- args = {
90
- "HostName" => ip,
91
- "User" => username,
92
- "IdentityFile" => DEFAULT_IDENTIFY_FILE_PATH,
93
- }
94
- args.each do |key, value|
95
- config.set(hostname, key, value)
96
- end
97
- config.save
98
- end
99
-
100
- def reset_mutagen_session(mutagen_config:, hostname:)
101
- return if mutagen_config.nil?
102
- alpha_dir = mutagen_config[:alpha]
103
- beta_dir = mutagen_config[:beta]
104
-
105
- return if alpha_dir.nil? || beta_dir.nil?
106
-
107
- terminate_mutagen_session
108
- create_mutagen_session(
109
- alpha_dir: alpha_dir,
110
- beta_dir: beta_dir,
111
- hostname: hostname,
112
- )
113
-
114
- if OS.linux?
115
- watch_alpha(alpha_dir: alpha_dir)
116
- end
117
- end
118
-
119
- def terminate_mutagen_session
120
- puts "Terminating mutagen session..."
121
- terminate_mutagen_command =
122
- %Q(mutagen terminate --label-selector=#{LABEL})
123
- terminate_mutagen_stdout,
124
- terminate_mutagen_stderr,
125
- terminate_mutagen_status =
126
- Open3.capture3(terminate_mutagen_command)
127
-
128
- if not terminate_mutagen_status.success?
129
- # mutagen prints to stdout and stderr
130
- msg = "Failed to terminate mutagen sessions: " \
131
- "#{terminate_mutagen_stdout} -" \
132
- "#{terminate_mutagen_stderr}"
133
- fail msg
134
- end
135
- end
136
-
137
- def create_mutagen_session(alpha_dir:, beta_dir:, hostname:)
138
- puts "Create mutagen session syncing local #{alpha_dir} " \
139
- "with #{hostname} #{beta_dir}"
140
-
141
- create_mutagen_command = [
142
- "mutagen sync create",
143
- alpha_dir,
144
- "#{hostname}:#{beta_dir}",
145
- "--label=#{LABEL}",
146
- ]
147
- create_mutagen_command << "--watch-mode-alpha=no-watch" if OS.linux?
148
-
149
- create_mutagen_stdout,
150
- create_mutagen_stderr,
151
- create_mutagen_status =
152
- Open3.capture3(create_mutagen_command.join(" "))
153
-
154
- if not create_mutagen_status.success?
155
- # mutagen prints to stdout and stderr
156
- msg = "Failed to create mutagen sessions: " \
157
- "#{create_mutagen_stdout} -" \
158
- "#{create_mutagen_stderr}"
159
- fail msg
160
- end
161
- end
162
-
163
- def watch_alpha(alpha_dir:)
164
- watchman = Watchman.new(dir: alpha_dir)
165
- watchman.trigger("mutagen sync flush --label-selector=#{LABEL}")
166
- end
14
+ Box.new(account, options).start
167
15
  end
168
16
 
169
17
  end
@@ -0,0 +1,222 @@
1
+ module DevboxLauncher
2
+ class Box
3
+
4
+ WAIT_BOOT_RESCUED_EXCEPTIONS = [
5
+ Net::SSH::ConnectionTimeout,
6
+ Net::SSH::Disconnect,
7
+ Errno::ECONNRESET,
8
+ Errno::ETIMEDOUT,
9
+ ]
10
+ WAIT_BOOT_IN_SECONDS = 10.freeze
11
+ MAX_BOOT_RETRIES = 10
12
+ DEFAULT_IDENTIFY_FILE_PATH = "~/.ssh/google_compute_engine".freeze
13
+ SSH_CONFIG_PATH = File.expand_path("~/.ssh/config").freeze
14
+ CONFIG_PATH = File.expand_path("~/.devbox_launcher.yml").freeze
15
+ CONFIG = YAML.load_file(CONFIG_PATH).freeze
16
+
17
+ attr_reader :account, :options
18
+
19
+ def initialize(account, options)
20
+ @account = account
21
+ @options = options
22
+ end
23
+
24
+ def start
25
+ start_stdout, start_stderr, start_status =
26
+ Open3.capture3(start_cmd)
27
+
28
+ set_ssh_config!
29
+
30
+ wait_boot
31
+
32
+ reset_mutagen_session
33
+
34
+ connect_mosh
35
+ end
36
+
37
+ def start_cmd
38
+ args = {
39
+ project: config[:project],
40
+ account: account,
41
+ }.map do |(key, val)|
42
+ ["--#{key}", val].join("=")
43
+ end.join(" ")
44
+
45
+ [
46
+ "gcloud",
47
+ "compute",
48
+ "instances",
49
+ "start",
50
+ name,
51
+ args
52
+ ].join(" ")
53
+ end
54
+
55
+ def connect_mosh
56
+ return if options[:mosh].nil?
57
+
58
+ mosh_cmd = %Q(mosh #{hostname})
59
+ system(mosh_cmd)
60
+ end
61
+
62
+ def wait_boot(tries: 1)
63
+ Net::SSH.start(hostname, username, timeout: WAIT_BOOT_IN_SECONDS) do |ssh|
64
+ puts "[#{ssh.exec!('date').chomp}] Machine booted"
65
+ end
66
+ rescue *WAIT_BOOT_RESCUED_EXCEPTIONS
67
+ puts "Not booted. Waiting #{WAIT_BOOT_IN_SECONDS} seconds before trying again..."
68
+
69
+ sleep WAIT_BOOT_IN_SECONDS
70
+
71
+ if !description(reload: true).running?
72
+ puts "Detected that the machine is not running " \
73
+ "(status is #{description.status}). Booting it..."
74
+ start
75
+ end
76
+
77
+ fail if tries >= MAX_BOOT_RETRIES
78
+
79
+ wait_boot tries: tries+1
80
+ end
81
+
82
+ def description(reload: false)
83
+ return @description if !reload && @description
84
+
85
+ puts "Fetching box's description..."
86
+
87
+ describe_stdout, describe_stderr, describe_status =
88
+ Open3.capture3(describe_cmd)
89
+
90
+ if !describe_status.success?
91
+ msg = "Problem fetching the description of #{name}. "
92
+ msg += "Please ensure you can call `#{describe_cmd}`.\n"
93
+ msg += "Error:\n"
94
+ msg += describe_stderr
95
+ fail msg
96
+ end
97
+
98
+ @description = Description.new(describe_stdout)
99
+ end
100
+
101
+ def describe_cmd
102
+ args = {
103
+ project: config[:project],
104
+ account: account,
105
+ }.map do |(key, val)|
106
+ ["--#{key}", val].join("=")
107
+ end.join(" ")
108
+
109
+ [
110
+ "gcloud",
111
+ "compute",
112
+ "instances",
113
+ "describe",
114
+ name,
115
+ args
116
+ ].join(" ")
117
+ end
118
+
119
+ def set_ssh_config!
120
+ FileUtils.touch(SSH_CONFIG_PATH)
121
+ config = ConfigFile.new
122
+ args = {
123
+ "HostName" => description.ip,
124
+ "User" => username,
125
+ "IdentityFile" => DEFAULT_IDENTIFY_FILE_PATH,
126
+ }
127
+ args.each do |key, value|
128
+ config.set(hostname, key, value)
129
+ end
130
+ config.save
131
+ end
132
+
133
+ def reset_mutagen_session
134
+ return if !mutagen_config.configured?
135
+
136
+ terminate_mutagen_session
137
+ create_mutagen_session
138
+ watch_alpha if OS.linux?
139
+ end
140
+
141
+ def terminate_mutagen_session
142
+ puts "Terminating mutagen session..."
143
+ terminate_mutagen_cmd =
144
+ %Q(mutagen terminate --label-selector=#{label})
145
+ terminate_mutagen_stdout,
146
+ terminate_mutagen_stderr,
147
+ terminate_mutagen_status =
148
+ Open3.capture3(terminate_mutagen_cmd)
149
+
150
+ if not terminate_mutagen_status.success?
151
+ # mutagen prints to stdout and stderr
152
+ msg = "Failed to terminate mutagen sessions: " \
153
+ "#{terminate_mutagen_stdout} -" \
154
+ "#{terminate_mutagen_stderr}"
155
+ fail msg
156
+ end
157
+ end
158
+
159
+ def label
160
+ "#{username}=#{name}"
161
+ end
162
+
163
+ def create_mutagen_session
164
+ puts "Create mutagen session syncing local " \
165
+ "#{mutagen_config.alpha_dir} with " \
166
+ "#{hostname} #{mutagen_config.beta_dir}"
167
+
168
+ create_mutagen_cmd = [
169
+ "mutagen sync create",
170
+ mutagen_config.alpha_dir,
171
+ "#{hostname}:#{mutagen_config.beta_dir}",
172
+ "--label=#{label}",
173
+ ]
174
+ create_mutagen_cmd << "--watch-mode-alpha=no-watch" if OS.linux?
175
+
176
+ create_mutagen_stdout,
177
+ create_mutagen_stderr,
178
+ create_mutagen_status =
179
+ Open3.capture3(create_mutagen_cmd.join(" "))
180
+
181
+ if not create_mutagen_status.success?
182
+ # mutagen prints to stdout and stderr
183
+ msg = "Failed to create mutagen sessions: " \
184
+ "#{create_mutagen_stdout} -" \
185
+ "#{create_mutagen_stderr}"
186
+ fail msg
187
+ end
188
+ end
189
+
190
+ def watch_alpha
191
+ watchman = Watchman.new(dir: mutagen_config.alpha_dir)
192
+ watchman.trigger("mutagen sync flush --label-selector=#{label}")
193
+ end
194
+
195
+ def name
196
+ @name ||= config[:box]
197
+ end
198
+
199
+ def hostname
200
+ [name, username, "devbox"].join("-")
201
+ end
202
+
203
+ def username
204
+ @username ||= account.gsub(/\W/, "_")
205
+ end
206
+
207
+ def config
208
+ return @config if @config
209
+
210
+ if not CONFIG.has_key?(account)
211
+ fail "No config in #{CONFIG_PATH} found for #{account}"
212
+ end
213
+
214
+ @config = CONFIG[account].with_indifferent_access
215
+ end
216
+
217
+ def mutagen_config
218
+ @mutagen_config ||= Mutagen.new(config[:mutagen])
219
+ end
220
+
221
+ end
222
+ end
@@ -0,0 +1,32 @@
1
+ module DevboxLauncher
2
+ class Description
3
+
4
+ def initialize(yaml)
5
+ @desc = YAML.load(yaml)
6
+ end
7
+
8
+ def ip
9
+ return @ip if @ip
10
+ network_interface = network_interfaces.first
11
+ access_configs = network_interface["accessConfigs"]
12
+
13
+ access_config = access_configs.find do |c|
14
+ c["kind"] == "compute#accessConfig"
15
+ end
16
+ @ip = access_config["natIP"]
17
+ end
18
+
19
+ def status
20
+ @status ||= @desc["status"]
21
+ end
22
+
23
+ def network_interfaces
24
+ @network_interfaces ||= @desc["networkInterfaces"]
25
+ end
26
+
27
+ def running?
28
+ status == "RUNNING"
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,23 @@
1
+ module DevboxLauncher
2
+ class Mutagen
3
+
4
+ attr_reader :config
5
+
6
+ def initialize(config)
7
+ @config = config
8
+ end
9
+
10
+ def configured?
11
+ [config, alpha_dir, beta_dir].none?(&:nil?)
12
+ end
13
+
14
+ def alpha_dir
15
+ config[:alpha]
16
+ end
17
+
18
+ def beta_dir
19
+ config[:beta]
20
+ end
21
+
22
+ end
23
+ end
@@ -1,3 +1,3 @@
1
1
  module DevboxLauncher
2
- VERSION = "0.3.0"
2
+ VERSION = "0.3.5"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: devbox_launcher
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ramon Tayag
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-01-24 00:00:00.000000000 Z
11
+ date: 2020-11-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -164,7 +164,7 @@ dependencies:
164
164
  - - '='
165
165
  - !ruby/object:Gem::Version
166
166
  version: 0.0.2
167
- description:
167
+ description:
168
168
  email:
169
169
  - ramon.tayag@gmail.com
170
170
  executables:
@@ -189,7 +189,11 @@ files:
189
189
  - bin/setup
190
190
  - devbox_launcher.gemspec
191
191
  - lib/devbox_launcher.rb
192
+ - lib/devbox_launcher/box.rb
192
193
  - lib/devbox_launcher/cli.rb
194
+ - lib/devbox_launcher/models/box.rb
195
+ - lib/devbox_launcher/models/description.rb
196
+ - lib/devbox_launcher/models/mutagen.rb
193
197
  - lib/devbox_launcher/version.rb
194
198
  - lib/devbox_launcher/watchman.rb
195
199
  homepage: https://github.com/bloom-solutions/devbox_launcher
@@ -200,7 +204,7 @@ metadata:
200
204
  homepage_uri: https://github.com/bloom-solutions/devbox_launcher
201
205
  source_code_uri: https://github.com/bloom-solutions/devbox_launcher
202
206
  changelog_uri: https://github.com/bloom-solutions/devbox_launcher/blob/master/CHANGELOG.md
203
- post_install_message:
207
+ post_install_message:
204
208
  rdoc_options: []
205
209
  require_paths:
206
210
  - lib
@@ -215,8 +219,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
215
219
  - !ruby/object:Gem::Version
216
220
  version: '0'
217
221
  requirements: []
218
- rubygems_version: 3.0.6
219
- signing_key:
222
+ rubygems_version: 3.0.8
223
+ signing_key:
220
224
  specification_version: 4
221
225
  summary: Conveniently launch your devbox
222
226
  test_files: []