vps 0.1.1 → 0.2.3

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
  SHA1:
3
- metadata.gz: d879c725aca451c863ec504e4fd4f7f9089bb5b0
4
- data.tar.gz: b0ebe2d831c630da62eb6e8c69452aebbcae4dcc
3
+ metadata.gz: 0715c15db0c61c43f427cde770c38cde3f65e677
4
+ data.tar.gz: 62fbbc6d56af47c025031dd5125ab7a4072d546d
5
5
  SHA512:
6
- metadata.gz: b750774204e6f237175c568f6528b9196a1bdf272193cc8ca1bfbfc7d77a539da72835f7160a2998532ae670c576312dcad2dc5eff6e8b3870e7801d68bb0992
7
- data.tar.gz: 84ed1b982a9d6e66d70a74845b2a33cbc4ed2c87f2830ae2b3a37b9cb6607ccd30bd870040f2b50a4aa882e0f5c0aeab1f1b194e2c045dce5b1113d393a8f025
6
+ metadata.gz: 0850d9d9a5888d1162e7cb491906f0afea445f82535a68ae03014b6304cb594c7c81f765f14325bf0b1d295a1a88a7e07ac009859f6d5c0ba727d3fee34988a8
7
+ data.tar.gz: 7c6dfffa4ce37dc82012bf13865cc03f9feb6367c1565305f5a7461f88fe73d951fccd502fbfc6544df7505f50fb1de15feabdef5ec29bffd682cfc0a768f1be
@@ -1,5 +1,30 @@
1
1
  ## VPS CHANGELOG
2
2
 
3
+ ### Version 0.2.3 (January 2, 2020)
4
+
5
+ * Support upstreams without domains
6
+
7
+ ### Version 0.2.2 (January 2, 2020)
8
+
9
+ * Automatically add container names for upstreams and services
10
+ * Add opportunity to add lines to the generated Dockerfile
11
+
12
+ ### Version 0.2.1 (January 2, 2020)
13
+
14
+ * Support NodeJS based applications
15
+ * Clean up default upstream specs
16
+ * Set container name when adding upstream
17
+
18
+ ### Version 0.2.0 (December 31, 2019)
19
+
20
+ * Provide ability to add both custom HTTP and HTTPS Nginx configs
21
+
22
+ ### Version 0.1.2 (September 29, 2019)
23
+
24
+ * Run postload tasks at the end of deployment
25
+ * Fix generating Rails and Rack Dockerfile (installing the correct Bundler version)
26
+ * Include configured :services in the generated docker-compose.yml file
27
+
3
28
  ### Version 0.1.1 (August 12, 2019)
4
29
 
5
30
  * Initial release
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.2.3
data/lib/vps.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require "tmpdir"
1
2
  require "vps/version"
2
3
 
3
4
  module VPS
@@ -16,6 +16,7 @@ require "active_support/number_helper"
16
16
 
17
17
  require "vps"
18
18
  require "vps/core_ext/string"
19
+ require "vps/core_ext/ostruct"
19
20
  require "vps/cli/service"
20
21
  require "vps/cli/upstream"
21
22
  require "vps/cli/domain"
@@ -11,7 +11,7 @@ module VPS
11
11
 
12
12
  if (upstream = config[:upstreams].detect{|upstream| upstream[:name] == name})
13
13
  upstream[:email] = email if email
14
- upstream[:domains].push(domain).uniq!
14
+ (upstream[:domains] ||= []).push(domain).uniq!
15
15
  VPS.write_config(host, config)
16
16
  end
17
17
  end
@@ -57,7 +57,7 @@ module VPS
57
57
  (hash || {}).fetch(key)
58
58
  end.tap do |value|
59
59
  if to_domain && value
60
- if (domain = value[:domains].first)
60
+ if (domain = (value[:domains] || ["-"]).first)
61
61
  return domain.gsub(/https?:\/\//, "")
62
62
  end
63
63
  end
@@ -9,18 +9,11 @@ module VPS
9
9
  path = File.expand_path(path)
10
10
 
11
11
  unless config[:upstreams].any?{|upstream| upstream[:name] == name}
12
- type, tool_version, port = derive_upstream(path)
13
- config[:upstreams].push({
12
+ spec = derive_upstream(path)
13
+ config[:upstreams].push(spec.merge({
14
14
  :name => name || File.basename(path),
15
- :path => path,
16
- :type => type,
17
- :tool_version => tool_version,
18
- :port => port,
19
- :domains => [],
20
- :email => nil,
21
- :compose => nil,
22
- :nginx => nil
23
- })
15
+ :path => path
16
+ }))
24
17
  VPS.write_config(host, config)
25
18
  end
26
19
  end
@@ -65,19 +58,42 @@ module VPS
65
58
  |> IO.puts()
66
59
  ELIXIR
67
60
  type = `cd #{path} && mix run -e "#{elixir.strip.gsub(/\n\s+/, " ")}" | tail -n 1`.strip
68
- [
69
- type,
70
- `cd #{path} && mix run -e "System.version() |> IO.puts()" | tail -n 1`.strip,
71
- (type == "phoenix") ? 4000 : `cd #{path} && mix run -e ":ranch.info |> hd() |> elem(0) |> :ranch.get_port() |> IO.puts()" | tail -n 1`.strip.to_i
72
- ]
61
+ {
62
+ type: type,
63
+ elixir_version: `cd #{path} && mix run -e "System.version() |> IO.puts()" | tail -n 1`.strip,
64
+ port: (type == "phoenix") ? 4000 : `cd #{path} && mix run -e ":ranch.info |> hd() |> elem(0) |> :ranch.get_port() |> IO.puts()" | tail -n 1`.strip.to_i
65
+ }
73
66
  elsif Dir["#{path}/Gemfile"].any?
74
67
  lines = `cd #{path} && BUNDLE_GEMFILE=#{path}/Gemfile bundle list`.split("\n")
75
68
  type = %w(rails rack).detect{|gem| lines.any?{|line| line.include?("* #{gem} (")}}
76
- [
77
- type,
78
- `$SHELL -l -c 'cd #{path} && ruby -e "puts RUBY_VERSION"'`.strip,
79
- (type == "rails" ? 3000 : 9292) # :'(
80
- ]
69
+ {
70
+ type: type,
71
+ ruby_version: `$SHELL -l -c 'cd #{path} && ruby -e "puts RUBY_VERSION"'`.strip,
72
+ bundler_version: `$SHELL -l -c 'cd #{path} && bundle -v'`.split.last,
73
+ port: (type == "rails" ? 3000 : 9292) # :'(
74
+ }.tap do |spec|
75
+ if type == "rails"
76
+ spec[:nginx] = {
77
+ root: "/opt/app/public",
78
+ try_files: true,
79
+ proxy_redirect: "off"
80
+ }
81
+ end
82
+ end
83
+ elsif Dir["#{path}/package.json"].any?
84
+ tmpfile = "#{Dir.tmpdir}/vps-debug.log"
85
+ pid = spawn("cd #{path} && npm start", :out => tmpfile, :err => "/dev/null")
86
+ Process.detach(pid)
87
+ sleep 5
88
+ `ps aux | grep -e "no[d]e #{path}"`.strip.split("\n").collect do |line|
89
+ `kill -9 #{line.split(" ")[1]}`
90
+ end
91
+ port = File.read(tmpfile).match(/on port (\d+)/).captures.first.to_i
92
+ {
93
+ type: "node",
94
+ node_version: `$SHELL -l -c 'cd #{path} && node -v'`.match(/[\d\.?]+/).to_s,
95
+ port: port
96
+ }
81
97
  end
82
98
  end
83
99
 
@@ -0,0 +1,17 @@
1
+ class OpenStruct
2
+ def self.to_hash(object, hash = {})
3
+ case object
4
+ when OpenStruct then
5
+ object.each_pair do |key, value|
6
+ hash[key.to_s] = to_hash(value)
7
+ end
8
+ hash
9
+ when Array then
10
+ object.collect do |value|
11
+ to_hash(value)
12
+ end
13
+ else
14
+ object
15
+ end
16
+ end
17
+ end
@@ -1,7 +1,7 @@
1
1
  module VPS
2
2
  MAJOR = 0
3
- MINOR = 1
4
- TINY = 1
3
+ MINOR = 2
4
+ TINY = 3
5
5
 
6
6
  VERSION = [MAJOR, MINOR, TINY].join(".")
7
7
  end
@@ -86,11 +86,11 @@ tasks:
86
86
  command:
87
87
  - chmod +x {{ release_path }}/init-letsencrypt/{{ upstream.name }}.sh
88
88
  - cd {{ release_path }} && if [ ! -d "data/certbot/conf/live/{{ domain:upstream }}" ]; then yes Y | sudo ./init-letsencrypt/{{ upstream.name }}.sh; fi
89
- - task: run_tasks
90
- tasks: << postload >>
91
89
  - description: Starting containers
92
90
  task: remote_execute
93
91
  command: cd {{ release_path }} && docker-compose up {{ up }} -d
94
92
  - description: Checking running docker images
95
93
  task: remote_execute
96
94
  command: docker ps
95
+ - task: run_tasks
96
+ tasks: << postload >>
@@ -3,19 +3,26 @@
3
3
  upstream <%= upstream[:name] %> {
4
4
  server <%= upstream[:name] %>:<%= upstream[:port] %>;
5
5
  }
6
- <%- upstream[:domains].partition{|domain| domain.include?("http://")}.reject(&:empty?).each do |domains| %>
6
+ <%- (upstream[:domains] || []).partition{|domain| domain.include?("http://")}.reject(&:empty?).each do |domains| %>
7
7
  <%-
8
8
  https = domains.first.include?("https://")
9
9
  domains = domains.collect{|domain| domain.gsub(/https?:\/\//, "")}.join(" ")
10
10
  domain = domains.split(" ")[0]
11
+ nginx = upstream[:nginx] || {}
11
12
  proxy_pass = "http://#{ upstream[:name] }"
12
13
  %>
13
14
 
14
15
  server {
16
+ <%- unless domains.empty? %>
15
17
  listen 80;
16
18
  server_name <%= domains %>;
17
19
  server_tokens off;
18
20
 
21
+ <%- end %>
22
+ <%- if nginx[:http] %>
23
+ <%= nginx[:http].gsub("PROXY_PASS", proxy_pass).indent(2) %>
24
+
25
+ <%- end %>
19
26
  <%- if https %>
20
27
  location /.well-known/acme-challenge/ {
21
28
  root /var/www/certbot;
@@ -37,15 +44,25 @@ server {
37
44
  ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
38
45
 
39
46
  <%- end %>
40
- <%- if upstream[:nginx] %>
41
- <%= upstream[:nginx].gsub("PROXY_PASS", proxy_pass).indent(2) %>
47
+ <%- if nginx[:root] %>
48
+ root <%= nginx[:root] %>;
49
+ <%- end %>
50
+ <%- if nginx[:try_files] %>
51
+ try_files $uri @app;
42
52
 
43
53
  <%- end %>
44
- location / {
54
+ <%- if nginx[:https] %>
55
+ <%= nginx[:https].gsub("PROXY_PASS", proxy_pass).indent(2) %>
56
+
57
+ <%- end %>
58
+ location <%= nginx[:try_files] ? "@app" : "/" %> {
45
59
  proxy_pass <%= proxy_pass %>;
46
60
  proxy_set_header Host $http_host;
47
61
  proxy_set_header X-Real-IP $remote_addr;
48
62
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
63
+ <%- if nginx[:proxy_redirect] %>
64
+ proxy_redirect <%= nginx[:proxy_redirect] %>;
65
+ <%- end %>
49
66
  }
50
67
  }
51
68
  <%- end %>
@@ -1,10 +1,5 @@
1
1
  version: "3"
2
- <%
3
- https = upstreams.any?{|upstream| upstream[:domains].any?{|domain| domain.include?("https://")}}
4
- to_yaml = proc do |struct|
5
- struct.to_h.inject({}){|h, (k, v)| h[k.to_s] = v; h}.to_yaml
6
- end
7
- %>
2
+ <% https = upstreams.any?{|upstream| upstream[:domains].any?{|domain| domain.include?("https://")}} %>
8
3
  services:
9
4
 
10
5
  nginx:
@@ -28,7 +23,7 @@ services:
28
23
  command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
29
24
 
30
25
  certbot:
31
- image: certbot/certbot
26
+ image: certbot/certbot:v0.27.1
32
27
  container_name: certbot
33
28
  restart: unless-stopped
34
29
  volumes:
@@ -36,21 +31,29 @@ services:
36
31
  - ./data/certbot/www:/var/www/certbot
37
32
  entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
38
33
  <%- end %>
34
+ <%- services.to_h.each do |name, spec| %>
35
+
36
+ <%= name %>:
37
+ <%= OpenStruct.to_hash(spec).to_yaml.sub(/^.*?\n/, "").sub("\n", "\ncontainer_name: #{name}\n").indent(4) %>
38
+ <%- end %>
39
39
  <%- upstreams.each do |upstream| %>
40
40
 
41
41
  <%= upstream.name %>:
42
42
  image: <%= upstream.name %>
43
+ container_name: <%= upstream.name %>
43
44
  restart: always
44
45
  <%- unless upstream[:compose].inspect.match(/\bports\b/) %>
45
46
  ports:
46
47
  - <%= upstream.port %>
47
48
  <%- end %>
48
49
  <%- if upstream[:compose] %>
49
- <%= to_yaml.(upstream[:compose]).sub(/^.*?\n/, "").indent(4) %>
50
+ <%= OpenStruct.to_hash(upstream[:compose]).to_yaml.sub(/^.*?\n/, "").indent(4) %>
50
51
  <%- end %>
51
52
  <%- end %>
52
- <%- services.each do |service, config| %>
53
+ <%- unless (volumes || []).empty? %>
53
54
 
54
- <%= service %>:
55
- <%= to_yaml.(config).sub(/^.*?\n/, "").indent(4) %>
56
- <%- end %>
55
+ volumes:
56
+ <%- volumes.each do |volume| %>
57
+ <%= volume %>:
58
+ <%- end %>
59
+ <%- end %>
@@ -0,0 +1,15 @@
1
+ FROM node:<%= upstream.node_version %>-alpine
2
+
3
+ RUN apk update \
4
+ && apk --no-cache --update add \
5
+ build-base nodejs tzdata
6
+
7
+ WORKDIR /opt/app
8
+ COPY . .
9
+
10
+ ENV NODE_ENV=production
11
+ <%- if upstream.dockerfile %>
12
+ <%= upstream.dockerfile.strip %>
13
+ <%- end %>
14
+ RUN npm install
15
+ CMD ["npm", "start"]
@@ -1,4 +1,4 @@
1
- FROM elixir:<%= upstream.tool_version %>-alpine
1
+ FROM elixir:<%= upstream.elixir_version %>-alpine
2
2
 
3
3
  RUN apk update \
4
4
  && apk --no-cache --update add alpine-sdk \
@@ -9,5 +9,8 @@ WORKDIR /opt/app
9
9
  COPY . .
10
10
 
11
11
  ENV MIX_ENV=prod
12
+ <%- if upstream.dockerfile %>
13
+ <%= upstream.dockerfile.strip %>
14
+ <%- end %>
12
15
  RUN mix do deps.get --only prod, deps.compile
13
16
  CMD ["sh", "-c", "mix phx.server"]
@@ -1,4 +1,4 @@
1
- FROM elixir:<%= upstream.tool_version %>-alpine
1
+ FROM elixir:<%= upstream.elixir_version %>-alpine
2
2
 
3
3
  RUN apk update \
4
4
  && apk --no-cache --update add alpine-sdk \
@@ -9,5 +9,8 @@ WORKDIR /opt/app
9
9
  COPY . .
10
10
 
11
11
  ENV MIX_ENV=prod
12
+ <%- if upstream.dockerfile %>
13
+ <%= upstream.dockerfile.strip %>
14
+ <%- end %>
12
15
  RUN mix do deps.get --only prod, deps.compile
13
16
  CMD ["sh", "-c", "mix run --no-halt"]
@@ -1,4 +1,4 @@
1
- FROM ruby:<%= upstream.tool_version %>-alpine
1
+ FROM ruby:<%= upstream.ruby_version %>-alpine
2
2
 
3
3
  RUN apk update \
4
4
  && apk --no-cache --update add \
@@ -11,5 +11,9 @@ WORKDIR /opt/app
11
11
  COPY . .
12
12
 
13
13
  ENV RACK_ENV=production
14
+ <%- if upstream.dockerfile %>
15
+ <%= upstream.dockerfile.strip %>
16
+ <%- end %>
17
+ RUN gem install bundler -v <%= upstream.bundler_version %>
14
18
  RUN bundle install --without development test
15
- CMD ["rackup", "config.ru", "-o", "0.0.0.0"]
19
+ CMD ["bundle", "exec", "rackup", "config.ru", "-o", "0.0.0.0"]
@@ -1,4 +1,4 @@
1
- FROM ruby:<%= upstream.tool_version %>-alpine
1
+ FROM ruby:<%= upstream.ruby_version %>-alpine
2
2
 
3
3
  RUN apk update \
4
4
  && apk --no-cache --update add \
@@ -10,6 +10,13 @@ RUN apk update \
10
10
  WORKDIR /opt/app
11
11
  COPY . .
12
12
 
13
+ EXPOSE <%= upstream.port %>
14
+
13
15
  ENV RAILS_ENV=production
16
+ <%- if upstream.dockerfile %>
17
+ <%= upstream.dockerfile.strip %>
18
+ <%- end %>
19
+ RUN gem install bundler -v <%= upstream.bundler_version %>
14
20
  RUN bundle install --without development test
21
+ CMD ["rm", "-f", "tmp/pids/server.pid"]
15
22
  CMD ["rails", "server", "-b", "0.0.0.0"]
@@ -1,6 +1,6 @@
1
1
  #!/bin/bash
2
2
 
3
- <%- if (domains = upstream[:domains].collect{|domain| domain.dup.gsub!("https://", "")}.compact).any? %>
3
+ <%- if (domains = (upstream[:domains] || []).collect{|domain| domain.dup.gsub!("https://", "")}.compact).any? %>
4
4
  domains=(<%= domains.join(" ") %>)
5
5
  email="<%= upstream[:email] || "noreply@#{domains.first}" %>" # Adding a valid address is strongly recommended
6
6
  data_path="./data/certbot"
@@ -17,8 +17,8 @@ fi
17
17
  if [ ! -e "$data_path/conf/options-ssl-nginx.conf" ] || [ ! -e "$data_path/conf/ssl-dhparams.pem" ]; then
18
18
  echo "### Downloading recommended TLS parameters ..."
19
19
  mkdir -p "$data_path/conf"
20
- curl -s https://raw.githubusercontent.com/certbot/certbot/master/certbot-nginx/certbot_nginx/tls_configs/options-ssl-nginx.conf > "$data_path/conf/options-ssl-nginx.conf"
21
- curl -s https://raw.githubusercontent.com/certbot/certbot/master/certbot/ssl-dhparams.pem > "$data_path/conf/ssl-dhparams.pem"
20
+ curl -s https://raw.githubusercontent.com/certbot/certbot/v0.40.1/certbot-nginx/certbot_nginx/tls_configs/options-ssl-nginx.conf > "$data_path/conf/options-ssl-nginx.conf"
21
+ curl -s https://raw.githubusercontent.com/certbot/certbot/v0.40.1/certbot/ssl-dhparams.pem > "$data_path/conf/ssl-dhparams.pem"
22
22
  echo
23
23
  fi
24
24
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vps
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Engel
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-08-12 00:00:00.000000000 Z
11
+ date: 2020-01-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -162,6 +162,7 @@ files:
162
162
  - lib/vps/cli/playbook/tasks.rb
163
163
  - lib/vps/cli/service.rb
164
164
  - lib/vps/cli/upstream.rb
165
+ - lib/vps/core_ext/ostruct.rb
165
166
  - lib/vps/core_ext/string.rb
166
167
  - lib/vps/version.rb
167
168
  - playbooks/deploy.yml
@@ -173,6 +174,7 @@ files:
173
174
  - script/console
174
175
  - templates/docker/data/nginx/app.conf.erb
175
176
  - templates/docker/docker-compose.yml.erb
177
+ - templates/docker/upstream/Dockerfile.node.erb
176
178
  - templates/docker/upstream/Dockerfile.phoenix.erb
177
179
  - templates/docker/upstream/Dockerfile.plug.erb
178
180
  - templates/docker/upstream/Dockerfile.rack.erb