devbox_launcher 0.3.4 → 0.5.2

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: 5d79623bafc3e14c6b9f9f58a8031282a334d8ea833e188546d1bffa4ffc1c10
4
- data.tar.gz: 350a59f18358ba1c473aed63dd033b3699b658e69a02d63bd7d29306a57bd695
3
+ metadata.gz: 51aeda9106ca067ea8ceb40899eeced91677bebb5de13b036280190d22980e16
4
+ data.tar.gz: b2852f7051db8ec6c4ce7e071aa256cab13b64af69455a774d4d18e9b949db75
5
5
  SHA512:
6
- metadata.gz: d25e43064171246a712be3a2ab71d2b30d5a3a58891bdeb84538293004147ed6a2b5f7bea5054e66cf433b5a47c0bce154a9aa2649e863e282c5a4a9d95a89dd
7
- data.tar.gz: 59102e2931d6327865ddc9bb87706dd31bffd703b618a7c9b05735062ac4c0cf69852b9b70be89223f99ee8f82858ceeb6091f7d784b3f43339402f9b070731f
6
+ metadata.gz: c84b3cb6f48286ea756546429c3e2d6bf6121b0f4632207bf37779e1f0a4611eb4126b6d24645a81b34738cb178c3cc06ec3046c606fa92a8bc65a71665474b0
7
+ data.tar.gz: 2585520ba4fb389c731b9f8fcca88b453ac6dbb91e82b9a466341d32e68ee773a42b481f106a400d1d5f5ea31b12358db098fb53f7ae6e6312cd7ec117a6b500
data/CHANGELOG.md CHANGED
@@ -4,6 +4,29 @@ 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
+
14
+ ## [0.5.1] - 2021-04-08
15
+ ### Fixed
16
+ - Use configured `zone` for describe as well
17
+
18
+ ## [0.5.0] - 2021-04-06
19
+ ### Added
20
+ - Ability to specify `zone` in config
21
+
22
+ ## [0.4.0]
23
+ ### Added
24
+ - Sync mutagen with two-way-resolved
25
+
26
+ ## [0.3.5]
27
+ ### Fixed
28
+ - When running commands, also rescue from whitelist of exceptions, and retry
29
+
7
30
  ## [0.3.4]
8
31
  ### Added
9
32
  - Rescue from `Errno::ECONNREFUSED` and retry
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- devbox_launcher (0.3.4)
4
+ devbox_launcher (0.5.2)
5
5
  activesupport (~> 6.0)
6
6
  bcrypt_pbkdf (~> 1.0)
7
7
  ed25519 (~> 1.2)
@@ -14,31 +14,31 @@ PATH
14
14
  GEM
15
15
  remote: https://rubygems.org/
16
16
  specs:
17
- activesupport (6.0.3.1)
17
+ activesupport (6.1.3.2)
18
18
  concurrent-ruby (~> 1.0, >= 1.0.2)
19
- i18n (>= 0.7, < 2)
20
- minitest (~> 5.1)
21
- tzinfo (~> 1.1)
22
- zeitwerk (~> 2.2, >= 2.2.2)
23
- bcrypt_pbkdf (1.0.1)
19
+ i18n (>= 1.6, < 2)
20
+ minitest (>= 5.1)
21
+ tzinfo (~> 2.0)
22
+ zeitwerk (~> 2.3)
23
+ bcrypt_pbkdf (1.1.0)
24
24
  byebug (11.0.1)
25
25
  coderay (1.1.2)
26
- concurrent-ruby (1.1.6)
26
+ concurrent-ruby (1.1.8)
27
27
  diff-lcs (1.3)
28
28
  ed25519 (1.2.4)
29
- i18n (1.8.2)
29
+ i18n (1.8.10)
30
30
  concurrent-ruby (~> 1.0)
31
31
  method_source (0.9.2)
32
- minitest (5.14.1)
32
+ minitest (5.14.4)
33
33
  net-ssh (5.2.0)
34
- os (1.1.0)
34
+ os (1.1.1)
35
35
  pry (0.12.2)
36
36
  coderay (~> 1.1.0)
37
37
  method_source (~> 0.9.0)
38
38
  pry-byebug (3.7.0)
39
39
  byebug (~> 11.0)
40
40
  pry (~> 0.10)
41
- rake (10.5.0)
41
+ rake (13.0.1)
42
42
  rspec (3.9.0)
43
43
  rspec-core (~> 3.9.0)
44
44
  rspec-expectations (~> 3.9.0)
@@ -54,11 +54,10 @@ GEM
54
54
  rspec-support (3.9.0)
55
55
  ruby-watchman (0.0.2)
56
56
  ssh-config (0.1.3)
57
- thor (1.0.1)
58
- thread_safe (0.3.6)
59
- tzinfo (1.2.7)
60
- thread_safe (~> 0.1)
61
- zeitwerk (2.3.0)
57
+ thor (1.1.0)
58
+ tzinfo (2.0.4)
59
+ concurrent-ruby (~> 1.0)
60
+ zeitwerk (2.4.2)
62
61
 
63
62
  PLATFORMS
64
63
  ruby
@@ -67,7 +66,7 @@ DEPENDENCIES
67
66
  bundler (~> 2.0)
68
67
  devbox_launcher!
69
68
  pry-byebug
70
- rake (~> 10.0)
69
+ rake (~> 13.0)
71
70
  rspec (~> 3.0)
72
71
 
73
72
  BUNDLED WITH
data/README.md CHANGED
@@ -4,13 +4,9 @@ Start devboxes quickly
4
4
 
5
5
  ## Installation
6
6
 
7
- Install the gem:
8
-
9
- ```sh
10
- gem install devbox_launcher
11
- ```
12
-
13
- Setup gcloud init with the project that contains your VM.
7
+ - Install the gem: `gem install devbox_launcher`
8
+ - Setup `gcloud init` with the project that contains your VM
9
+ - Install [mutagen](https://mutagen.io)
14
10
 
15
11
  ## Usage
16
12
 
@@ -21,6 +17,9 @@ Create the config file at `~/.devbox_launcher.yml` so you type less. This is an
21
17
  ```yml
22
18
  ramon@email.com:
23
19
  project: general-192303
20
+ # zone not necessarily required, but sometimes starting the box
21
+ # fails without this:
22
+ zone: us-central1-a
24
23
  box: your-instance-name
25
24
  mutagen:
26
25
  alpha: /mnt/c/Users/me/src # local machine
@@ -36,7 +35,7 @@ To start and create the mutagen session:
36
35
  devbox start your-username
37
36
  ```
38
37
 
39
- If you want to mosh in immediately, add the `--mosh` switch.
38
+ If you want to mosh in immediately, add the `--mosh` switch. Yes, mosh needs to be [installed](https://mosh.org/) in your development machine.
40
39
 
41
40
  Note: Linux users that sync mutagen sessions need to install [Watchman](https://facebook.github.io/watchman/).
42
41
 
@@ -30,7 +30,7 @@ Gem::Specification.new do |spec|
30
30
  spec.require_paths = ["lib"]
31
31
 
32
32
  spec.add_development_dependency "bundler", "~> 2.0"
33
- spec.add_development_dependency "rake", "~> 10.0"
33
+ spec.add_development_dependency "rake", "~> 13.0"
34
34
  spec.add_development_dependency "rspec", "~> 3.0"
35
35
 
36
36
  spec.add_runtime_dependency "thor", "~> 1.0"
@@ -1,4 +1,5 @@
1
1
  require "active_support/core_ext/hash/indifferent_access"
2
+ require "active_support/core_ext/object/blank"
2
3
  require "ssh-config"
3
4
  require "open3"
4
5
  require "thor"
@@ -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 = 10
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
@@ -35,21 +36,7 @@ module DevboxLauncher
35
36
  end
36
37
 
37
38
  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(" ")
39
+ cmd_args_for('start')
53
40
  end
54
41
 
55
42
  def connect_mosh
@@ -82,8 +69,6 @@ module DevboxLauncher
82
69
  def description(reload: false)
83
70
  return @description if !reload && @description
84
71
 
85
- puts "Fetching box's description..."
86
-
87
72
  describe_stdout, describe_stderr, describe_status =
88
73
  Open3.capture3(describe_cmd)
89
74
 
@@ -99,21 +84,7 @@ module DevboxLauncher
99
84
  end
100
85
 
101
86
  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(" ")
87
+ cmd_args_for('describe')
117
88
  end
118
89
 
119
90
  def set_ssh_config!
@@ -218,5 +189,26 @@ module DevboxLauncher
218
189
  @mutagen_config ||= Mutagen.new(config[:mutagen])
219
190
  end
220
191
 
192
+ def cmd_args_for(method)
193
+ args = {
194
+ project: config[:project],
195
+ account: account,
196
+ zone: config[:zone],
197
+ }.each_with_object([]) do |(key, val), arr|
198
+ next if val.blank?
199
+ arr << ["--#{key}", val].join("=")
200
+ end.join(" ")
201
+
202
+ [
203
+ "gcloud",
204
+ "compute",
205
+ "instances",
206
+ method,
207
+ name,
208
+ args
209
+ ].join(" ")
210
+ end
211
+
212
+
221
213
  end
222
214
  end
@@ -1,3 +1,3 @@
1
1
  module DevboxLauncher
2
- VERSION = "0.3.4"
2
+ VERSION = "0.5.2"
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.4
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: 2020-11-17 00:00:00.000000000 Z
11
+ date: 2021-05-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '10.0'
33
+ version: '13.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '10.0'
40
+ version: '13.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -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
@@ -219,7 +218,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
219
218
  - !ruby/object:Gem::Version
220
219
  version: '0'
221
220
  requirements: []
222
- rubygems_version: 3.0.8
221
+ rubygems_version: 3.1.4
223
222
  signing_key:
224
223
  specification_version: 4
225
224
  summary: Conveniently launch your devbox
@@ -1,206 +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
- Open3.capture3(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
- Open3.capture3(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
- Open3.capture3(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
- Open3.capture3(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
- end
206
- end