fly.io-rails 0.1.13-x86_64-darwin → 0.1.14-x86_64-darwin

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: fcfaec6d850537e8996be5433afdb03535220ac28e220476eda290f007db8869
4
- data.tar.gz: 425394a56bef440ee2203c68eb23b45fee353448184bbd8007d4037b145ab316
3
+ metadata.gz: e9f2574745e0ea8f2edbac0856d08111f2bcd5832883ef5bedb8cfc0fafcfcb1
4
+ data.tar.gz: 41071616ae60e7e10973ff8eb4ca80dc8c959783160da33259cfc1c14055fd7f
5
5
  SHA512:
6
- metadata.gz: 509ca70e091879017f22dba9b8df8aeaabee3c8f4303c16bfa671e61da82db6b8631eaa311247d0e22cfb692b67b412d192707d6cba4e97a810ae296c051e272
7
- data.tar.gz: f3018185e5949ff74abb8969fc1866a2f81a1b042e1ffc79c0490c1d114cdc98e777f4002f5f64fbc0630216c70e190a166a18f9f5a011e258dede717866668b
6
+ metadata.gz: ccfe3797a1be8049d57c606a0d0b4274c08143fc5b68af6e188797df83f5b8fd9f565b032b0ad36dbbfe8247e9f59e811a732fcf633195d3f693199d83ce662b
7
+ data.tar.gz: a923ba90ff095ab64dd0500452aebfad5c1c902f7ba064c2c2085fb51e5c880f8e009c3d6ab40680d3edd187c8f0cd7c741ee7634bf976c27ff3cf59726f5d83
Binary file
@@ -26,6 +26,7 @@ module Fly
26
26
  regions = options[:region]&.flatten || []
27
27
  @avahi = options[:avahi]
28
28
  @litefs = options[:litefs]
29
+ @nats = options[:nats]
29
30
  @nomad = options[:nomad]
30
31
  @passenger = options[:passenger]
31
32
  @serverless = options[:serverless]
@@ -36,6 +37,7 @@ module Fly
36
37
  @node = File.exist? 'node_modules'
37
38
  @yarn = File.exist? 'yarn.lock'
38
39
  @node_version = @node ? `node --version`.chomp.sub(/^v/, '') : '16.17.0'
40
+ @yarn_version = @yarn ? `yarn --version`.chomp : 'latest'
39
41
  @org = Fly::Machines.org
40
42
 
41
43
  @set_stage = @nomad ? 'set' : 'set --stage'
@@ -402,15 +404,23 @@ module Fly
402
404
  # start app
403
405
  machines = {}
404
406
  say_status :fly, "start #{app}"
405
- if not toml['processes']
407
+ if not toml['processes'] or toml['processes'].empty?
406
408
  start = Fly::Machines.create_and_start_machine(app, config: config)
407
409
  machines['app'] = start[:id]
408
410
  else
409
411
  config[:env] ||= {}
412
+ config[:env]['NATS_SERVER'] = 'localhost'
410
413
  toml['processes'].each do |name, entrypoint|
411
414
  config[:env]['SERVER_COMMAND'] = entrypoint
412
415
  start = Fly::Machines.create_and_start_machine(app, config: config)
413
416
  machines[name] = start[:id]
417
+
418
+ config.delete :mounts
419
+ config.delete :services
420
+
421
+ if config[:env]['NATS_SERVER'] = 'localhost'
422
+ config[:env]['NATS_SERVER'] = start[:private_ip]
423
+ end
414
424
  end
415
425
  end
416
426
 
@@ -1,3 +1,3 @@
1
1
  module Fly_io
2
- VERSION = '0.1.13'
2
+ VERSION = '0.1.14'
3
3
  end
@@ -12,6 +12,7 @@ class AppGenerator < Rails::Generators::Base
12
12
  class_option :anycable, type: :boolean, default: false
13
13
  class_option :avahi, type: :boolean, default: false
14
14
  class_option :litefs, type: :boolean, default: false
15
+ class_option :nats, type: :boolean, default: false
15
16
  class_option :redis, type: :boolean, default: false
16
17
  class_option :passenger, type: :boolean, default: false
17
18
  class_option :serverless, type: :boolean, default: false
@@ -25,6 +25,7 @@ LABEL fly_launch_runtime="rails"
25
25
 
26
26
  <% if @node -%>
27
27
  ARG NODE_VERSION=<%= @node_version %>
28
+ ARG YARN_VERSION=<%= @yarn_version %>
28
29
  <% end -%>
29
30
  ARG BUNDLER_VERSION=<%= @bundler_version %>
30
31
 
@@ -50,7 +51,7 @@ RUN mkdir -p tmp/pids
50
51
  RUN curl https://get.volta.sh | bash
51
52
  ENV VOLTA_HOME /root/.volta
52
53
  ENV PATH $VOLTA_HOME/bin:/usr/local/bin:$PATH
53
- RUN volta install node@${NODE_VERSION} yarn
54
+ RUN volta install node@${NODE_VERSION} yarn@${YARN_VERSION}
54
55
 
55
56
  <% end -%>
56
57
  #######################################################################
@@ -139,10 +140,11 @@ RUN apt-get install -y dirmngr gnupg apt-transport-https ca-certificates curl &&
139
140
  @deploy_packages << 'libsqlite3-0' if @sqlite3
140
141
  @deploy_packages << 'default-mysql-client' if @mysql
141
142
  @deploy_packages << 'imagemagick' if @rmagick
142
- @deploy_packages << 'nodejs' if not @node and @boostrap
143
+ @deploy_packages << 'nodejs' if not @node and @bootstrap
143
144
  @deploy_packages << 'fuse' if @litefs
144
145
  @deploy_packages << 'ruby-foreman' if @procs.length > 1
145
146
  @deploy_packages << 'redis-server' if @redis == :internal
147
+ @deploy_packages << 'gettext-base' if @nats
146
148
  @deploy_packages += %w(avahi-daemon avahi-utils libnss-mdns) if @avahi
147
149
  -%>
148
150
  ARG DEPLOY_PACKAGES=<%= @deploy_packages.join(' ').inspect %>
@@ -187,6 +189,14 @@ ADD config/litefs.yml /etc/litefs.yml
187
189
 
188
190
  # Create mount point
189
191
  RUN mkdir /data
192
+
193
+ <% end -%>
194
+ <% if @nats -%>
195
+ # install nats
196
+ RUN mkdir /etc/nats
197
+ COPY --from=nats:latest /nats-server /usr/local/bin/nats-server
198
+ COPY --from=nats:latest /nats-server.conf /etc/nats/nats-server.conf
199
+
190
200
  <% end -%>
191
201
  #######################################################################
192
202
  <% if @avahi -%>
@@ -197,7 +207,9 @@ RUN sed -i 's/mdns4_minimal/mdns_minimal/' /etc/nsswitch.conf
197
207
  <% if @passenger -%>
198
208
 
199
209
  # configure nginx/passenger
210
+ <% unless @avahi or @nats -%>
200
211
  COPY config/nginx.conf /etc/nginx/sites-available/rails.conf
212
+ <% end -%>
201
213
  RUN rm /etc/nginx/sites-enabled/default && \
202
214
  ln -s /etc/nginx/sites-available/rails.conf /etc/nginx/sites-enabled/ && \
203
215
  sed -i 's/user .*;/user root;/' /etc/nginx/nginx.conf && \
@@ -18,10 +18,16 @@ namespace :fly do
18
18
  <%- end -%>
19
19
 
20
20
  <% end -%>
21
- <% if @avahi -%>
21
+ <% if @avahi or @nats -%>
22
22
  task :env do
23
23
  <% if @redis -%>
24
- ENV['REDIS_URL'] = "redis://#{ENV['FLY_REGION']}-redis.local:6379/1"
24
+ if ENV['NATS_SERVER']
25
+ redis_host = "#{ENV['FLY_REGION']}-redis.local"
26
+ else
27
+ redis_host = 'localhost'
28
+ end
29
+
30
+ ENV['REDIS_URL'] = "redis://#{redis_host}:6379/1"
25
31
  <% end -%>
26
32
  <% if @anycable -%>
27
33
  ENV['ANYCABLE_GO_RPC_HOST'] = "#{ENV['FLY_REGION']}-anycable-rpc.local:50051"
@@ -46,13 +52,18 @@ namespace :fly do
46
52
  end
47
53
  end %>
48
54
  <%- if @procs.length > 1 -%>
49
- formation = args[:formation] || <%= @procs.keys.map {|key| "#{key}=1"}.join(';').inspect %>
50
- formation.gsub! ';', ','
55
+ <%- if @passenger and (@avahi or @nats) -%>
56
+ sh 'envsubst < config/nginx.conf > /etc/nginx/sites-available/rails.conf'
57
+ <%- end -%>
58
+ formation = args[:formation].gsub!(';', ',')
51
59
  <%- if @avahi -%>
52
60
  Rake::Task['fly:avahi_publish'].invoke(formation)
53
61
  <%- end -%>
62
+ <%- if @nats -%>
63
+ Rake::Task['fly:nats_publish'].invoke(formation) if ENV['NATS_SERVER']
64
+ <%- end -%>
54
65
  Bundler.with_original_env do
55
- <%- if @avahi -%>
66
+ <%- if @avahi or @nats -%>
56
67
  Rake::Task['fly:env'].invoke
57
68
  <%- end -%>
58
69
  sh "foreman start --procfile=Procfile.fly --formation=#{formation}"
@@ -1,7 +1,7 @@
1
1
  app = "<%= @app %>"
2
2
  kill_signal = "SIGINT"
3
3
  kill_timeout = 5
4
- <% unless @avahi -%>
4
+ <% unless @avahi or @nats -%>
5
5
  processes = []
6
6
  <% end -%>
7
7
 
@@ -25,10 +25,10 @@ processes = []
25
25
  <% else -%>
26
26
  DATABASE_URL = "sqlite3:///mnt/volume/production.sqlite3"
27
27
  <% end -%>
28
- <% if @avahi -%>
28
+ <% if @avahi or @nats -%>
29
29
 
30
30
  [processes]
31
- app = "bin/rails fly:server[<%= @procs.keys.map {|key| "#{key}=1"}.join(';') %>]"
31
+ app = "bin/rails fly:server[<%= @procs.keys.map {|key| "#{key}=1"}.join(';') %>]"
32
32
  <% end -%>
33
33
 
34
34
  [mounts]
@@ -21,11 +21,19 @@ server {
21
21
 
22
22
  <% if @anycable -%>
23
23
  location /cable {
24
+ <%- if @passenger and (@avahi or @nats) -%>
25
+ proxy_pass http://${FLY_REGION}-anycable-go.local:8082/cable;
26
+ proxy_http_version 1.1;
27
+ proxy_set_header Upgrade $${_0_}http_upgrade;
28
+ proxy_set_header Connection "Upgrade";
29
+ proxy_set_header Host $${_0_}host;
30
+ <%- else -%>
24
31
  proxy_pass http://localhost:8082/cable;
25
32
  proxy_http_version 1.1;
26
33
  proxy_set_header Upgrade $http_upgrade;
27
34
  proxy_set_header Connection "Upgrade";
28
35
  proxy_set_header Host $host;
36
+ <%- end -%>
29
37
  }
30
38
 
31
39
  <% elsif @cable -%>
data/lib/tasks/fly.rake CHANGED
@@ -2,6 +2,7 @@ require 'fly.io-rails/machines'
2
2
  require 'fly.io-rails/hcl'
3
3
  require 'fly.io-rails/actions'
4
4
  require 'toml'
5
+ require 'json'
5
6
 
6
7
  namespace :fly do
7
8
  desc 'Deploy fly application'
@@ -58,6 +59,72 @@ namespace :fly do
58
59
  sh 'dbus-daemon --config-file=/usr/share/dbus-1/system.conf --print-address'
59
60
  end
60
61
 
62
+ desc 'nats based service discovery'
63
+ task :nats_publish, [:formation] do |task, args|
64
+ nats_server = ENV['NATS_SERVER']
65
+
66
+ # start nats server
67
+ if nats_server == 'localhost'
68
+ pid = spawn('nats-server')
69
+ at_exit { Process.kill 7, pid }
70
+ else
71
+ open('/etc/hosts', 'a') do |file|
72
+ host = "#{ENV['FLY_REGION']}-nats-server.local"
73
+ file.puts "#{nats_server}\t#{host}"
74
+ nats_server = host
75
+ end
76
+ end
77
+
78
+ # determine our local 6pn network address
79
+ address = IPSocket.getaddress('fly-local-6pn')
80
+
81
+ # Determine which applications we need addresses for and
82
+ # which applications we can provide addresses for.
83
+ hosts = {}
84
+ needs = []
85
+ args[:formation].scan(/([-\w]+)=(\d+)/).each do |name, count|
86
+ dnsname = "#{ENV['FLY_REGION']}-#{name}.local"
87
+ needs << dnsname
88
+ hosts[dnsname] = address unless count.to_i == 0
89
+ end
90
+
91
+ # share and collect hosts
92
+ require 'nats/client'
93
+ nats = NATS.connect(nats_server)
94
+
95
+ nats.subscribe('query_hosts') do |msg|
96
+ msg.respond hosts.to_json
97
+ end
98
+
99
+ update_hosts = Proc.new do |msg|
100
+ addresses = JSON.parse(msg.data)
101
+
102
+ open('/etc/hosts', 'r+') do |file|
103
+ file.flock(File::LOCK_EX)
104
+ contents = file.read
105
+
106
+ addresses.each do |dnsname, address|
107
+ file.puts "#{address}\t#{dnsname}" unless contents.include? dnsname
108
+ end
109
+ end
110
+
111
+ needs -= hosts.keys
112
+ end
113
+
114
+ nats.request('query_hosts', &update_hosts)
115
+ nats.subscribe('advertise_hosts', &update_hosts)
116
+
117
+ nats.publish('advertise_hosts', hosts.to_json)
118
+
119
+ at_exit { nats.close }
120
+
121
+ # wait for dependencies to be available
122
+ 600.times do
123
+ break if needs.empty?
124
+ sleep 0.1
125
+ end
126
+ end
127
+
61
128
  desc 'Zeroconf/avahi/bonjour discovery'
62
129
  task :avahi_publish, [:formation] => :dbus_deamon do |task, args|
63
130
  pids = []
@@ -70,6 +137,29 @@ namespace :fly do
70
137
  pids << spawn("avahi-publish -a -R #{ENV['FLY_REGION']}-#{name}.local #{ip}")
71
138
  end
72
139
 
140
+ require 'resolv'
141
+ 100.times do
142
+ begin
143
+ map = {}
144
+ args[:formation].scan(/([-\w]+)=(\d+)/).each do |name, count|
145
+ dnsname = "#{ENV['FLY_REGION']}-#{name}.local"
146
+ resolve = `avahi-resolve-host-name #{dnsname}`
147
+ raise Resolv::ResolvError.new if $?.exitstatus > 0 or resolve.empty?
148
+ map[dnsname] = resolve.split.last
149
+ end
150
+
151
+ open('/etc/hosts', 'a') do |hosts|
152
+ map.each do |dnsname, address|
153
+ hosts.puts "#{address} #{dnsname}"
154
+ end
155
+ end
156
+
157
+ break
158
+ rescue Resolv::ResolvError
159
+ sleep 0.1
160
+ end
161
+ end
162
+
73
163
  at_exit do
74
164
  pids.each {|pid| Process.kill 7, pid}
75
165
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fly.io-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.13
4
+ version: 0.1.14
5
5
  platform: x86_64-darwin
6
6
  authors:
7
7
  - Sam Ruby
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-10-18 00:00:00.000000000 Z
11
+ date: 2022-10-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fly-ruby
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: nats-pure
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  description:
42
56
  email: rubys@intertwingly.net
43
57
  executables: