devbox_launcher 0.5.1 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/Gemfile.lock +3 -3
- data/lib/devbox_launcher/models/box.rb +2 -3
- data/lib/devbox_launcher/version.rb +1 -1
- metadata +2 -3
- data/lib/devbox_launcher/box.rb +0 -214
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 51aeda9106ca067ea8ceb40899eeced91677bebb5de13b036280190d22980e16
|
4
|
+
data.tar.gz: b2852f7051db8ec6c4ce7e071aa256cab13b64af69455a774d4d18e9b949db75
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c84b3cb6f48286ea756546429c3e2d6bf6121b0f4632207bf37779e1f0a4611eb4126b6d24645a81b34738cb178c3cc06ec3046c606fa92a8bc65a71665474b0
|
7
|
+
data.tar.gz: 2585520ba4fb389c731b9f8fcca88b453ac6dbb91e82b9a466341d32e68ee773a42b481f106a400d1d5f5ea31b12358db098fb53f7ae6e6312cd7ec117a6b500
|
data/CHANGELOG.md
CHANGED
@@ -4,6 +4,13 @@ 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.5.2] - 2021-05-31
|
8
|
+
### Added
|
9
|
+
- Ignore VCS as recommended by mutagen
|
10
|
+
|
11
|
+
### Fixed
|
12
|
+
- Retry on `Errno::ECONNREFUSED`
|
13
|
+
|
7
14
|
## [0.5.1] - 2021-04-08
|
8
15
|
### Fixed
|
9
16
|
- Use configured `zone` for describe as well
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
devbox_launcher (0.5.
|
4
|
+
devbox_launcher (0.5.2)
|
5
5
|
activesupport (~> 6.0)
|
6
6
|
bcrypt_pbkdf (~> 1.0)
|
7
7
|
ed25519 (~> 1.2)
|
@@ -14,7 +14,7 @@ PATH
|
|
14
14
|
GEM
|
15
15
|
remote: https://rubygems.org/
|
16
16
|
specs:
|
17
|
-
activesupport (6.1.3)
|
17
|
+
activesupport (6.1.3.2)
|
18
18
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
19
19
|
i18n (>= 1.6, < 2)
|
20
20
|
minitest (>= 5.1)
|
@@ -26,7 +26,7 @@ GEM
|
|
26
26
|
concurrent-ruby (1.1.8)
|
27
27
|
diff-lcs (1.3)
|
28
28
|
ed25519 (1.2.4)
|
29
|
-
i18n (1.8.
|
29
|
+
i18n (1.8.10)
|
30
30
|
concurrent-ruby (~> 1.0)
|
31
31
|
method_source (0.9.2)
|
32
32
|
minitest (5.14.4)
|
@@ -6,9 +6,10 @@ module DevboxLauncher
|
|
6
6
|
Net::SSH::Disconnect,
|
7
7
|
Errno::ECONNRESET,
|
8
8
|
Errno::ETIMEDOUT,
|
9
|
+
Errno::ECONNREFUSED,
|
9
10
|
]
|
10
11
|
WAIT_BOOT_IN_SECONDS = 10.freeze
|
11
|
-
MAX_BOOT_RETRIES =
|
12
|
+
MAX_BOOT_RETRIES = 20
|
12
13
|
DEFAULT_IDENTIFY_FILE_PATH = "~/.ssh/google_compute_engine".freeze
|
13
14
|
SSH_CONFIG_PATH = File.expand_path("~/.ssh/config").freeze
|
14
15
|
CONFIG_PATH = File.expand_path("~/.devbox_launcher.yml").freeze
|
@@ -68,8 +69,6 @@ module DevboxLauncher
|
|
68
69
|
def description(reload: false)
|
69
70
|
return @description if !reload && @description
|
70
71
|
|
71
|
-
puts "Fetching box's description..."
|
72
|
-
|
73
72
|
describe_stdout, describe_stderr, describe_status =
|
74
73
|
Open3.capture3(describe_cmd)
|
75
74
|
|
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.5.
|
4
|
+
version: 0.5.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ramon Tayag
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-05-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -189,7 +189,6 @@ files:
|
|
189
189
|
- bin/setup
|
190
190
|
- devbox_launcher.gemspec
|
191
191
|
- lib/devbox_launcher.rb
|
192
|
-
- lib/devbox_launcher/box.rb
|
193
192
|
- lib/devbox_launcher/cli.rb
|
194
193
|
- lib/devbox_launcher/models/box.rb
|
195
194
|
- lib/devbox_launcher/models/description.rb
|
data/lib/devbox_launcher/box.rb
DELETED
@@ -1,214 +0,0 @@
|
|
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
|
-
"--sync-mode=two-way-resolved",
|
162
|
-
]
|
163
|
-
create_mutagen_command << "--watch-mode-alpha=no-watch" if OS.linux?
|
164
|
-
|
165
|
-
create_mutagen_stdout,
|
166
|
-
create_mutagen_stderr,
|
167
|
-
create_mutagen_status =
|
168
|
-
run_command(create_mutagen_command.join(" "))
|
169
|
-
|
170
|
-
if not create_mutagen_status.success?
|
171
|
-
# mutagen prints to stdout and stderr
|
172
|
-
msg = "Failed to create mutagen sessions: " \
|
173
|
-
"#{create_mutagen_stdout} -" \
|
174
|
-
"#{create_mutagen_stderr}"
|
175
|
-
fail msg
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
|
-
def watch_alpha(alpha_dir:, hostname:)
|
180
|
-
watchman = Watchman.new(dir: alpha_dir)
|
181
|
-
watchman.trigger("mutagen sync flush --label-selector=#{hostname}")
|
182
|
-
end
|
183
|
-
|
184
|
-
def name
|
185
|
-
@name ||= config[:box]
|
186
|
-
end
|
187
|
-
|
188
|
-
def hostname
|
189
|
-
[name, username, "devbox"].join("-")
|
190
|
-
end
|
191
|
-
|
192
|
-
def username
|
193
|
-
@username ||= account.gsub(/\W/, "_")
|
194
|
-
end
|
195
|
-
|
196
|
-
def config
|
197
|
-
return @config if @config
|
198
|
-
|
199
|
-
if not CONFIG.has_key?(account)
|
200
|
-
fail "No config in #{CONFIG_PATH} found for #{account}"
|
201
|
-
end
|
202
|
-
|
203
|
-
@config = CONFIG[account].with_indifferent_access
|
204
|
-
end
|
205
|
-
|
206
|
-
def run_command(command, tries: 0)
|
207
|
-
Open3.capture3(command)
|
208
|
-
rescue *WAIT_BOOT_RESCUED_EXCEPTIONS
|
209
|
-
sleep WAIT_BOOT_IN_SECONDS
|
210
|
-
run_command(command, tries+1)
|
211
|
-
end
|
212
|
-
|
213
|
-
end
|
214
|
-
end
|