orchestration 0.2.8 → 0.3.0
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/.gitignore +1 -2
- data/.strong_versions.yml +2 -0
- data/Makefile +1 -0
- data/README.md +8 -5
- data/TODO +11 -7
- data/bin/strong_versions +29 -0
- data/config/locales/en.yml +10 -2
- data/lib/orchestration/docker_compose/application_service.rb +5 -10
- data/lib/orchestration/docker_compose/nginx_proxy_service.rb +5 -2
- data/lib/orchestration/docker_compose/services.rb +9 -2
- data/lib/orchestration/environment.rb +18 -2
- data/lib/orchestration/file_helpers.rb +28 -17
- data/lib/orchestration/install_generator.rb +45 -37
- data/lib/orchestration/services/application/configuration.rb +1 -1
- data/lib/orchestration/services/configuration_base.rb +1 -1
- data/lib/orchestration/templates/Dockerfile.erb +15 -4
- data/lib/orchestration/templates/Makefile.erb +23 -22
- data/lib/orchestration/templates/entrypoint.sh.erb +5 -3
- data/lib/orchestration/templates/nginx.tmpl.erb +364 -0
- data/lib/orchestration/templates/unicorn.rb.erb +1 -1
- data/lib/orchestration/templates/yaml.bash.erb +22 -0
- data/lib/orchestration/terminal.rb +12 -4
- data/lib/orchestration/version.rb +1 -1
- data/orchestration.gemspec +1 -0
- metadata +21 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 13a569a8391d7110efc2606ba1d486e29e342080
|
4
|
+
data.tar.gz: c5eed32f638f89dce179cd93c8f634504fe628d2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 91481f33e8f48bfabe18ab3c36fab7381060c631a62da15f3806197f7ec3ef08815a93790d132cf8431606eb6d110792f86c26fe3b7783a2e347a61f6e05a0cc
|
7
|
+
data.tar.gz: 32f5222a028460e9d5bb5b4477dae935a83692d7f50dae1e62d0b24b19fb3fb4db5c38453f2a1f9a787502868bb45d0a0284d9a99d331507c7cef9278ef7f7ac
|
data/.gitignore
CHANGED
data/Makefile
CHANGED
data/README.md
CHANGED
@@ -18,7 +18,7 @@ Containers are automatically created for the following dependencies:
|
|
18
18
|
Add this line to your application's Gemfile:
|
19
19
|
|
20
20
|
```ruby
|
21
|
-
gem 'orchestration', '~> 0.
|
21
|
+
gem 'orchestration', '~> 0.3.0'
|
22
22
|
```
|
23
23
|
|
24
24
|
And then build your bundle:
|
@@ -32,11 +32,14 @@ $ bundle install
|
|
32
32
|
|
33
33
|
A _Rake_ task is provided to generate the following files:
|
34
34
|
|
35
|
-
* `Makefile` - provides easy access to all _Orchestration_ utilities.
|
36
35
|
* `.gitignore` - ensures any unwanted files created by _Orchestration_ do not clutter your project's version control system.
|
37
|
-
* `docker/Dockerfile` - a ready-to-use _Docker_ build script which should need minimal (if any) modification to build your _Rails_ project.
|
38
|
-
* `docker-compose.yml` - a custom-made set of services to allow you to run your application's dependencies locally.
|
39
36
|
* `.orchestration.yml` - _Orchestration_ internal configuration, e.g. _Docker_ username.
|
37
|
+
* `Makefile` - Adds `orchestration/Makefile` as an `include` to avoid clobbering any existing _make_ commands.
|
38
|
+
* `orchestration/docker-compose.yml` - a custom-made set of services to allow you to run your application's dependencies locally.
|
39
|
+
* `orchestration/Dockerfile` - a ready-to-use _Docker_ build script which should need minimal (if any) modification to build your _Rails_ project.
|
40
|
+
* `orchestration/entrypoint.sh` - Container setup for your Docker application.
|
41
|
+
* `orchestration/Makefile` - provides easy access to all _Orchestration_ utilities.
|
42
|
+
* `orchestration/yaml.bash` - A _bash_ _YAML_ parser (used by _make_ utilities).
|
40
43
|
|
41
44
|
### Building and pushing your project as a _Docker_ image
|
42
45
|
|
@@ -47,7 +50,7 @@ If your project has any dependencies on private _Git_ repositories then you wil
|
|
47
50
|
* [GitHub](https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/)
|
48
51
|
* [Bitbucket](https://confluence.atlassian.com/bitbucket/app-passwords-828781300.html)
|
49
52
|
|
50
|
-
Create a file named `.env` in
|
53
|
+
Create a file named `.env` in your project's root directory and add one or both of the following (note that _Bitbucket_ and _GitHub_ use a different format):
|
51
54
|
|
52
55
|
```bash
|
53
56
|
BUNDLE_BITBUCKET__ORG=<bitbucket-username>:<app-password>
|
data/TODO
CHANGED
@@ -1,15 +1,19 @@
|
|
1
|
-
Be aware of yarn and include build steps in Dockerfile if present. Use dashboard
|
2
|
-
front end as a reference.
|
3
|
-
|
4
1
|
Provide volumes for databases and mount appropriate directories for adapter
|
5
2
|
|
6
3
|
Refactor docker-compose services - these really belong in
|
7
4
|
lib/orchestration/services/<service-name>/docker_compose.rb
|
8
5
|
|
9
|
-
Add a note to README to handle `RAILS_LOG_TO_STDOUT` in development -
|
10
|
-
unfortunately Rails ignores this value in development mode. (It's configured in
|
11
|
-
config/environments/production.rb)
|
12
|
-
|
13
6
|
Standardise on log formats - by policy or recommendation ?
|
14
7
|
|
15
8
|
Redis support
|
9
|
+
|
10
|
+
Stop supporting development mode. Provide a docker-compose.yml for loading
|
11
|
+
development and test dependencies and expect user to run Rails application
|
12
|
+
locally.
|
13
|
+
|
14
|
+
Build a docker-compose.production.yml for running application in
|
15
|
+
production (i.e. including application as a service and removing local port
|
16
|
+
bindings).
|
17
|
+
|
18
|
+
Make docker-compose file additive - detect existing services and add new ones
|
19
|
+
rather than overwriting.
|
data/bin/strong_versions
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'strong_versions' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("strong_versions", "strong_versions")
|
data/config/locales/en.yml
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
en:
|
2
2
|
orchestration:
|
3
3
|
attempt_limit: "Unable to reconnect after %{limit} attempts. Aborting."
|
4
|
+
default: "default"
|
4
5
|
|
5
6
|
application:
|
6
7
|
waiting: "Waiting for application: %{config}"
|
@@ -27,8 +28,15 @@ en:
|
|
27
28
|
waiting: "Waiting for [%{service}]: %{config}"
|
28
29
|
ready: "[%{service}] is ready."
|
29
30
|
|
30
|
-
|
31
|
-
|
31
|
+
settings:
|
32
|
+
docker:
|
33
|
+
username:
|
34
|
+
description: "Docker registry username"
|
35
|
+
prompt: "username"
|
36
|
+
|
37
|
+
repository:
|
38
|
+
description: "Project name (will be used as Docker registry repository)"
|
39
|
+
prompt: "project name"
|
32
40
|
|
33
41
|
rake:
|
34
42
|
docker:
|
@@ -9,22 +9,17 @@ module Orchestration
|
|
9
9
|
|
10
10
|
def definition
|
11
11
|
{
|
12
|
-
'image' =>
|
13
|
-
'entrypoint' => '/entrypoint.sh',
|
14
|
-
'command' => %w[
|
15
|
-
bundle exec unicorn -c /application/config/unicorn.rb
|
16
|
-
],
|
12
|
+
'image' => '${DOCKER_USERNAME}/${DOCKER_REPOSITORY}',
|
17
13
|
'environment' => environment,
|
18
|
-
'expose' => [8080]
|
14
|
+
'expose' => [8080],
|
15
|
+
'volumes' => [
|
16
|
+
"#{@config.env.public_volume}:/app/public/:ro"
|
17
|
+
]
|
19
18
|
}
|
20
19
|
end
|
21
20
|
|
22
21
|
private
|
23
22
|
|
24
|
-
def image
|
25
|
-
"#{@config.docker_username}/#{@config.application_name}"
|
26
|
-
end
|
27
|
-
|
28
23
|
def environment
|
29
24
|
{
|
30
25
|
'DATABASE_URL' => @config.database_url,
|
@@ -9,9 +9,12 @@ module Orchestration
|
|
9
9
|
|
10
10
|
def definition
|
11
11
|
{
|
12
|
-
'image' => '
|
12
|
+
'image' => 'rubyorchestration/nginx-proxy',
|
13
13
|
'ports' => %w[3000:80],
|
14
|
-
'volumes' => [
|
14
|
+
'volumes' => [
|
15
|
+
'/var/run/docker.sock:/tmp/docker.sock:ro',
|
16
|
+
"#{@config.env.public_volume}:/var/www/public/:ro"
|
17
|
+
]
|
15
18
|
}
|
16
19
|
end
|
17
20
|
end
|
@@ -3,7 +3,8 @@
|
|
3
3
|
module Orchestration
|
4
4
|
module DockerCompose
|
5
5
|
class Services
|
6
|
-
def initialize(options = {})
|
6
|
+
def initialize(env, options = {})
|
7
|
+
@env = env
|
7
8
|
@configurations = {
|
8
9
|
'application' => options.fetch(:application, nil),
|
9
10
|
'database' => options.fetch(:database, nil),
|
@@ -14,7 +15,13 @@ module Orchestration
|
|
14
15
|
end
|
15
16
|
|
16
17
|
def structure
|
17
|
-
{
|
18
|
+
{
|
19
|
+
'version' => '3.7',
|
20
|
+
'services' => services,
|
21
|
+
'volumes' => {
|
22
|
+
@env.public_volume => nil
|
23
|
+
}
|
24
|
+
}
|
18
25
|
end
|
19
26
|
|
20
27
|
def services
|
@@ -33,7 +33,7 @@ module Orchestration
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def docker_compose_configuration_path
|
36
|
-
|
36
|
+
orchestration_root.join('docker-compose.yml')
|
37
37
|
end
|
38
38
|
|
39
39
|
def docker_compose_config
|
@@ -44,10 +44,14 @@ module Orchestration
|
|
44
44
|
docker_compose_configuration_path.file?
|
45
45
|
end
|
46
46
|
|
47
|
-
def
|
47
|
+
def default_application_name
|
48
48
|
Rails.application.class.parent.name.underscore
|
49
49
|
end
|
50
50
|
|
51
|
+
def application_name
|
52
|
+
settings.get('docker.repository')
|
53
|
+
end
|
54
|
+
|
51
55
|
def settings
|
52
56
|
Settings.new(orchestration_configuration_path)
|
53
57
|
end
|
@@ -57,5 +61,17 @@ module Orchestration
|
|
57
61
|
|
58
62
|
Pathname.new(Dir.pwd)
|
59
63
|
end
|
64
|
+
|
65
|
+
def orchestration_root
|
66
|
+
root.join(orchestration_dir_name)
|
67
|
+
end
|
68
|
+
|
69
|
+
def orchestration_dir_name
|
70
|
+
'orchestration'
|
71
|
+
end
|
72
|
+
|
73
|
+
def public_volume
|
74
|
+
"#{application_name}_public"
|
75
|
+
end
|
60
76
|
end
|
61
77
|
end
|
@@ -4,45 +4,56 @@ module Orchestration
|
|
4
4
|
module FileHelpers
|
5
5
|
private
|
6
6
|
|
7
|
+
def orchestration_dir
|
8
|
+
path = @env.orchestration_root
|
9
|
+
FileUtils.mkdir(path) unless Dir.exist?(path)
|
10
|
+
|
11
|
+
path
|
12
|
+
end
|
13
|
+
|
7
14
|
def template(template_name, context = {})
|
8
15
|
Erubis::Eruby.new(read_template(template_name))
|
9
16
|
.result(context)
|
10
17
|
end
|
11
18
|
|
12
|
-
def
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
output = input[0...index] + pattern + replacement
|
18
|
-
|
19
|
-
return @terminal.write(:identical, relative_path(path)) if input == output
|
20
|
-
|
21
|
-
update_file(path, output)
|
22
|
-
end
|
23
|
-
|
24
|
-
def append_index(pattern, input)
|
25
|
-
return 0 if input.empty?
|
19
|
+
def inject_if_missing(path, content, index = 0)
|
20
|
+
lines = File.exist?(path) ? File.readlines(path).map(&:chomp) : []
|
21
|
+
if lines.any? { |line| line == content }
|
22
|
+
return @terminal.write(:skip, relative_path(path))
|
23
|
+
end
|
26
24
|
|
27
|
-
index
|
28
|
-
|
25
|
+
lines.insert(index, content)
|
26
|
+
update_file(path, lines.join("\n"))
|
29
27
|
end
|
30
28
|
|
31
29
|
def relative_path(path)
|
32
30
|
path.relative_path_from(Rails.root).to_s
|
33
31
|
end
|
34
32
|
|
33
|
+
def simple_copy(template_name, dest)
|
34
|
+
update_file(dest, template(template_name))
|
35
|
+
end
|
36
|
+
|
35
37
|
def write_file(path, content, options = {})
|
36
38
|
relpath = relative_path(path)
|
37
39
|
overwrite = options.fetch(:overwrite, true)
|
38
|
-
|
40
|
+
present = File.exist?(path)
|
41
|
+
return @terminal.write(:skip, relpath) if present && !overwrite
|
39
42
|
|
40
43
|
File.write(path, content)
|
41
44
|
@terminal.write(:create, relative_path(path))
|
42
45
|
end
|
43
46
|
|
44
47
|
def update_file(path, content)
|
48
|
+
present = File.exist?(path)
|
49
|
+
return write_file(path, content) unless present
|
50
|
+
|
51
|
+
previous_content = File.read(path) if present
|
45
52
|
File.write(path, content)
|
53
|
+
if present && previous_content == content
|
54
|
+
return @terminal.write(:skip, relative_path(path))
|
55
|
+
end
|
56
|
+
|
46
57
|
@terminal.write(:update, relative_path(path))
|
47
58
|
end
|
48
59
|
|
@@ -11,63 +11,61 @@ module Orchestration
|
|
11
11
|
super
|
12
12
|
@env = Environment.new
|
13
13
|
@terminal ||= Terminal.new
|
14
|
+
@settings = Settings.new(@env.orchestration_configuration_path)
|
14
15
|
end
|
15
16
|
|
16
17
|
def orchestration_configuration
|
17
18
|
path = @env.orchestration_configuration_path
|
18
|
-
|
19
|
-
|
19
|
+
ask_setting('docker.username')
|
20
|
+
ask_setting('docker.repository', @env.default_application_name)
|
20
21
|
relpath = relative_path(path)
|
21
|
-
return @terminal.write(:create, relpath) unless settings.exist?
|
22
|
-
return @terminal.write(:update, relpath) if settings.dirty?
|
22
|
+
return @terminal.write(:create, relpath) unless @settings.exist?
|
23
|
+
return @terminal.write(:update, relpath) if @settings.dirty?
|
23
24
|
|
24
25
|
@terminal.write(:skip, relpath)
|
25
26
|
end
|
26
27
|
|
27
28
|
def makefile
|
28
|
-
environment = {
|
29
|
-
app_id: @env.application_name,
|
30
|
-
wait_commands: wait_commands
|
31
|
-
}
|
29
|
+
environment = { env: @env, wait_commands: wait_commands }
|
32
30
|
content = template('Makefile', environment)
|
33
|
-
path = @env.
|
34
|
-
|
31
|
+
path = @env.orchestration_root.join('Makefile')
|
32
|
+
path.exist? ? update_file(path, content) : write_file(path, content)
|
33
|
+
inject_if_missing(
|
34
|
+
@env.root.join('Makefile'),
|
35
|
+
'include orchestration/Makefile'
|
36
|
+
)
|
35
37
|
end
|
36
38
|
|
37
39
|
def dockerfile
|
38
40
|
content = template('Dockerfile', ruby_version: RUBY_VERSION)
|
39
|
-
write_file(
|
41
|
+
write_file(
|
42
|
+
orchestration_dir.join('Dockerfile'),
|
43
|
+
content,
|
44
|
+
overwrite: false
|
45
|
+
)
|
40
46
|
end
|
41
47
|
|
42
48
|
def entrypoint
|
43
49
|
content = template('entrypoint.sh')
|
44
|
-
path =
|
50
|
+
path = orchestration_dir.join('entrypoint.sh')
|
45
51
|
write_file(path, content, overwrite: false)
|
46
52
|
FileUtils.chmod('a+x', path)
|
47
53
|
end
|
48
54
|
|
49
55
|
def gitignore
|
50
56
|
path = @env.root.join('.gitignore')
|
51
|
-
entries = [
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
'docker/*.gemspec'
|
56
|
-
]
|
57
|
+
entries = %w[.build/ Gemfile Gemfile.lock *.gemspec].map do |entry|
|
58
|
+
"#{@env.orchestration_dir_name}/#{entry}"
|
59
|
+
end
|
60
|
+
|
57
61
|
ensure_lines_in_file(path, entries)
|
58
62
|
end
|
59
63
|
|
60
64
|
def docker_compose
|
61
|
-
path = @env.
|
65
|
+
path = @env.orchestration_root.join('docker-compose.yml')
|
62
66
|
return if File.exist?(path)
|
63
67
|
|
64
|
-
docker_compose = DockerCompose::Services.new(
|
65
|
-
application: configuration(:application),
|
66
|
-
database: configuration(:database),
|
67
|
-
mongo: configuration(:mongo),
|
68
|
-
rabbitmq: configuration(:rabbitmq),
|
69
|
-
nginx_proxy: configuration(:nginx_proxy)
|
70
|
-
)
|
68
|
+
docker_compose = DockerCompose::Services.new(@env, service_configurations)
|
71
69
|
write_file(path, docker_compose.structure.to_yaml)
|
72
70
|
end
|
73
71
|
|
@@ -77,8 +75,24 @@ module Orchestration
|
|
77
75
|
write_file(path, content, overwrite: false)
|
78
76
|
end
|
79
77
|
|
78
|
+
def yaml_bash
|
79
|
+
simple_copy('yaml.bash', @env.orchestration_root.join('yaml.bash'))
|
80
|
+
end
|
81
|
+
|
80
82
|
private
|
81
83
|
|
84
|
+
def t(key)
|
85
|
+
I18n.t("orchestration.#{key}")
|
86
|
+
end
|
87
|
+
|
88
|
+
def service_configurations
|
89
|
+
Hash[
|
90
|
+
%i[application database mongo rabbitmq nginx_proxy].map do |key|
|
91
|
+
[key, configuration(key)]
|
92
|
+
end
|
93
|
+
]
|
94
|
+
end
|
95
|
+
|
82
96
|
def configuration(service)
|
83
97
|
{
|
84
98
|
application: Services::Application::Configuration,
|
@@ -99,18 +113,12 @@ module Orchestration
|
|
99
113
|
].compact.join(' ')
|
100
114
|
end
|
101
115
|
|
102
|
-
def
|
103
|
-
return unless settings.get(
|
104
|
-
|
105
|
-
@terminal.write(:setup, I18n.t('orchestration.docker.username_request'))
|
106
|
-
settings.set('docker.username', @terminal.read('[username]:'))
|
107
|
-
end
|
108
|
-
|
109
|
-
def docker_dir
|
110
|
-
path = @env.root.join('docker')
|
111
|
-
FileUtils.mkdir(path) unless Dir.exist?(path)
|
116
|
+
def ask_setting(setting, default = nil)
|
117
|
+
return unless @settings.get(setting).nil?
|
112
118
|
|
113
|
-
|
119
|
+
@terminal.write(:setup, t("settings.#{setting}.description"))
|
120
|
+
prompt = t("settings.#{setting}.prompt")
|
121
|
+
@settings.set(setting, @terminal.read(prompt, default))
|
114
122
|
end
|
115
123
|
end
|
116
124
|
end
|
@@ -5,9 +5,20 @@ RUN apt-get update \
|
|
5
5
|
&& apt-get install -y node.js gosu sendmail \
|
6
6
|
&& rm -rf /var/lib/apt/lists/* \
|
7
7
|
&& gem install bundler \
|
8
|
-
&& mkdir /
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
&& mkdir /app<%if defined?(Webpacker) %> \
|
9
|
+
&& curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash \
|
10
|
+
&& . /root/.bashrc \
|
11
|
+
&& nvm install 10.11.0 \
|
12
|
+
&& npm install -g yarn<% end %>
|
13
|
+
WORKDIR /app
|
14
|
+
COPY .build/Gemfile .build/Gemfile.lock ./
|
15
|
+
RUN bundle install --without development test --deployment
|
16
|
+
<% if defined?(Webpacker) %>
|
17
|
+
COPY .build/package.json .build/yarn.lock ./
|
18
|
+
RUN . /root/.bashrc && yarn install
|
19
|
+
<% end %>
|
12
20
|
COPY entrypoint.sh /
|
13
21
|
ADD .build/context.tar.gz .
|
22
|
+
<% if defined?(Webpacker) %>RUN . /root/.bashrc && yarn install && bundle exec rake assets:precompile<% else %>RUN bundle exec rake assets:precompile<% end %>
|
23
|
+
ENTRYPOINT ["/entrypoint.sh"]
|
24
|
+
CMD ["bundle", "exec", "unicorn", "-c", "/app/config/unicorn.rb"]
|
@@ -1,20 +1,10 @@
|
|
1
|
-
|
2
|
-
# Do not edit this file below this point. Any changes will be overwritten.
|
3
|
-
#
|
4
|
-
# Example `test` command which will start and wait for all services before
|
5
|
-
# running tests:
|
6
|
-
#
|
7
|
-
# test: start wait
|
8
|
-
# bundle exec rspec
|
9
|
-
# yarn test app/javascript
|
10
|
-
# bundle exec rubocop
|
11
|
-
# yarn run eslint app/javascript
|
12
|
-
#
|
13
|
-
.PHONY: start stop migrate docker build push start <%= wait_commands %>
|
1
|
+
.PHONY: start stop migrate docker build push start logs compose config <%= wait_commands %>
|
14
2
|
|
15
3
|
### Container management commands ###
|
16
4
|
|
17
|
-
|
5
|
+
DOCKER_USERNAME:=$(shell bash ./<%= env.orchestration_dir_name %>/yaml.bash docker_username)
|
6
|
+
DOCKER_REPOSITORY:=$(shell bash ./<%= env.orchestration_dir_name %>/yaml.bash docker_repository)
|
7
|
+
COMPOSE:=HOST_UID=$(shell id -u) DOCKER_USERNAME=${DOCKER_USERNAME} DOCKER_REPOSITORY=${DOCKER_REPOSITORY} docker-compose -p $(shell bash ./<%= env.orchestration_dir_name %>/yaml.bash docker_repository) -f orchestration/docker-compose.yml
|
18
8
|
|
19
9
|
start:
|
20
10
|
@echo "Starting containers..."
|
@@ -32,6 +22,15 @@ start-application:
|
|
32
22
|
@make wait-nginx-proxy wait-application
|
33
23
|
@echo "Application started."
|
34
24
|
|
25
|
+
logs:
|
26
|
+
@${COMPOSE} logs
|
27
|
+
|
28
|
+
config:
|
29
|
+
@${COMPOSE} config
|
30
|
+
|
31
|
+
compose:
|
32
|
+
@${COMPOSE} $$cmd
|
33
|
+
|
35
34
|
### Database utility commands ###
|
36
35
|
|
37
36
|
migrate: wait-database
|
@@ -67,19 +66,21 @@ GIT_BRANCH:=$(if $(BRANCH),$(BRANCH),$(shell git rev-parse --abbrev-ref HEAD))
|
|
67
66
|
|
68
67
|
build:
|
69
68
|
@echo "Preparing build from ${GIT_BRANCH}"
|
70
|
-
@mkdir -p
|
71
|
-
@git show ${GIT_BRANCH}:./Gemfile >
|
72
|
-
@git show ${GIT_BRANCH}:./Gemfile.lock >
|
69
|
+
@mkdir -p ./<%= env.orchestration_dir_name %>/.build
|
70
|
+
@git show ${GIT_BRANCH}:./Gemfile > ./<%= env.orchestration_dir_name %>/.build/Gemfile
|
71
|
+
@git show ${GIT_BRANCH}:./Gemfile.lock > ./<%= env.orchestration_dir_name %>/.build/Gemfile.lock
|
72
|
+
<% if defined?(Webpacker) %>@git show ${GIT_BRANCH}:./package.json > ./<%= env.orchestration_dir_name %>/.build/package.json<% end %>
|
73
|
+
<% if defined?(Webpacker) %>@git show ${GIT_BRANCH}:./yarn.lock > ./<%= env.orchestration_dir_name %>/.build/yarn.lock<% end %>
|
73
74
|
@echo "Building..."
|
74
|
-
@git archive --format tar.gz -o
|
75
|
+
@git archive --format tar.gz -o ./<%= env.orchestration_dir_name %>/.build/context.tar.gz ${GIT_BRANCH}
|
75
76
|
@docker build \
|
76
77
|
--build-arg BUNDLE_GITHUB__COM \
|
77
78
|
--build-arg BUNDLE_BITBUCKET__ORG \
|
78
|
-
-t $
|
79
|
-
-t $(shell
|
80
|
-
|
79
|
+
-t ${DOCKER_USERNAME}/${DOCKER_REPOSITORY} \
|
80
|
+
-t ${DOCKER_USERNAME}/${DOCKER_REPOSITORY}:$(shell git rev-parse --short --verify ${GIT_BRANCH}) \
|
81
|
+
./<%= env.orchestration_dir_name %>/
|
81
82
|
@echo "Build complete."
|
82
83
|
|
83
84
|
push: VERSION := $(shell git rev-parse --short --verify ${GIT_BRANCH})
|
84
85
|
push:
|
85
|
-
docker push $
|
86
|
+
docker push ${DOCKER_USERNAME}/${DOCKER_REPOSITORY}:${VERSION}
|
@@ -1,7 +1,9 @@
|
|
1
1
|
#!/bin/sh
|
2
2
|
set -u
|
3
3
|
id owner >/dev/null 2>&1 || useradd -u ${HOST_UID} -m -o owner
|
4
|
-
mkdir -p /
|
5
|
-
chown -R owner:owner /
|
6
|
-
rm -f /
|
4
|
+
mkdir -p /app/tmp/pids
|
5
|
+
chown -R owner:owner /app/tmp /app/log /app/db
|
6
|
+
rm -f /app/tmp/pids/unicorn.pid
|
7
|
+
mkdir -p /var/www/public/
|
8
|
+
ln -nfs /app/public/* /var/www/public/
|
7
9
|
exec gosu owner "$@"
|
@@ -0,0 +1,364 @@
|
|
1
|
+
{{ $CurrentContainer := where $ "ID" .Docker.CurrentContainerID | first }}
|
2
|
+
|
3
|
+
{{ define "upstream" }}
|
4
|
+
{{ if .Address }}
|
5
|
+
{{/* If we got the containers from swarm and this container's port is published to host, use host IP:PORT */}}
|
6
|
+
{{ if and .Container.Node.ID .Address.HostPort }}
|
7
|
+
# {{ .Container.Node.Name }}/{{ .Container.Name }}
|
8
|
+
server {{ .Container.Node.Address.IP }}:{{ .Address.HostPort }};
|
9
|
+
{{/* If there is no swarm node or the port is not published on host, use container's IP:PORT */}}
|
10
|
+
{{ else if .Network }}
|
11
|
+
# {{ .Container.Name }}
|
12
|
+
server {{ .Network.IP }}:{{ .Address.Port }};
|
13
|
+
{{ end }}
|
14
|
+
{{ else if .Network }}
|
15
|
+
# {{ .Container.Name }}
|
16
|
+
{{ if .Network.IP }}
|
17
|
+
server {{ .Network.IP }} down;
|
18
|
+
{{ else }}
|
19
|
+
server 127.0.0.1 down;
|
20
|
+
{{ end }}
|
21
|
+
{{ end }}
|
22
|
+
|
23
|
+
{{ end }}
|
24
|
+
|
25
|
+
# If we receive X-Forwarded-Proto, pass it through; otherwise, pass along the
|
26
|
+
# scheme used to connect to this server
|
27
|
+
map $http_x_forwarded_proto $proxy_x_forwarded_proto {
|
28
|
+
default $http_x_forwarded_proto;
|
29
|
+
'' $scheme;
|
30
|
+
}
|
31
|
+
|
32
|
+
# If we receive X-Forwarded-Port, pass it through; otherwise, pass along the
|
33
|
+
# server port the client connected to
|
34
|
+
map $http_x_forwarded_port $proxy_x_forwarded_port {
|
35
|
+
default $http_x_forwarded_port;
|
36
|
+
'' $server_port;
|
37
|
+
}
|
38
|
+
|
39
|
+
# If we receive Upgrade, set Connection to "upgrade"; otherwise, delete any
|
40
|
+
# Connection header that may have been passed to this server
|
41
|
+
map $http_upgrade $proxy_connection {
|
42
|
+
default upgrade;
|
43
|
+
'' close;
|
44
|
+
}
|
45
|
+
|
46
|
+
# Apply fix for very long server names
|
47
|
+
server_names_hash_bucket_size 128;
|
48
|
+
|
49
|
+
# Default dhparam
|
50
|
+
{{ if (exists "/etc/nginx/dhparam/dhparam.pem") }}
|
51
|
+
ssl_dhparam /etc/nginx/dhparam/dhparam.pem;
|
52
|
+
{{ end }}
|
53
|
+
|
54
|
+
# Set appropriate X-Forwarded-Ssl header
|
55
|
+
map $scheme $proxy_x_forwarded_ssl {
|
56
|
+
default off;
|
57
|
+
https on;
|
58
|
+
}
|
59
|
+
|
60
|
+
gzip_types text/plain text/css application/javascript application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
|
61
|
+
|
62
|
+
log_format vhost '$host $remote_addr - $remote_user [$time_local] '
|
63
|
+
'"$request" $status $body_bytes_sent '
|
64
|
+
'"$http_referer" "$http_user_agent"';
|
65
|
+
|
66
|
+
access_log off;
|
67
|
+
|
68
|
+
{{ if $.Env.RESOLVERS }}
|
69
|
+
resolver {{ $.Env.RESOLVERS }};
|
70
|
+
{{ end }}
|
71
|
+
|
72
|
+
{{ if (exists "/etc/nginx/proxy.conf") }}
|
73
|
+
include /etc/nginx/proxy.conf;
|
74
|
+
{{ else }}
|
75
|
+
# HTTP 1.1 support
|
76
|
+
proxy_http_version 1.1;
|
77
|
+
proxy_buffering off;
|
78
|
+
proxy_set_header Host $http_host;
|
79
|
+
proxy_set_header Upgrade $http_upgrade;
|
80
|
+
proxy_set_header Connection $proxy_connection;
|
81
|
+
proxy_set_header X-Real-IP $remote_addr;
|
82
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
83
|
+
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
|
84
|
+
proxy_set_header X-Forwarded-Ssl $proxy_x_forwarded_ssl;
|
85
|
+
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
|
86
|
+
|
87
|
+
# Mitigate httpoxy attack (see README for details)
|
88
|
+
proxy_set_header Proxy "";
|
89
|
+
{{ end }}
|
90
|
+
|
91
|
+
{{ $enable_ipv6 := eq (or ($.Env.ENABLE_IPV6) "") "true" }}
|
92
|
+
server {
|
93
|
+
server_name _; # This is just an invalid value which will never trigger on a real hostname.
|
94
|
+
listen 80;
|
95
|
+
{{ if $enable_ipv6 }}
|
96
|
+
listen [::]:80;
|
97
|
+
{{ end }}
|
98
|
+
access_log /var/log/nginx/access.log vhost;
|
99
|
+
return 503;
|
100
|
+
}
|
101
|
+
|
102
|
+
{{ if (and (exists "/etc/nginx/certs/default.crt") (exists "/etc/nginx/certs/default.key")) }}
|
103
|
+
server {
|
104
|
+
server_name _; # This is just an invalid value which will never trigger on a real hostname.
|
105
|
+
listen 443 ssl http2;
|
106
|
+
{{ if $enable_ipv6 }}
|
107
|
+
listen [::]:443 ssl http2;
|
108
|
+
{{ end }}
|
109
|
+
access_log /var/log/nginx/access.log vhost;
|
110
|
+
return 503;
|
111
|
+
|
112
|
+
ssl_session_tickets off;
|
113
|
+
ssl_certificate /etc/nginx/certs/default.crt;
|
114
|
+
ssl_certificate_key /etc/nginx/certs/default.key;
|
115
|
+
}
|
116
|
+
{{ end }}
|
117
|
+
|
118
|
+
{{ range $host, $containers := groupByMulti $ "Env.VIRTUAL_HOST" "," }}
|
119
|
+
|
120
|
+
{{ $host := trim $host }}
|
121
|
+
{{ $is_regexp := hasPrefix "~" $host }}
|
122
|
+
{{ $upstream_name := when $is_regexp (sha1 $host) $host }}
|
123
|
+
|
124
|
+
# {{ $host }}
|
125
|
+
upstream {{ $upstream_name }} {
|
126
|
+
|
127
|
+
{{ range $container := $containers }}
|
128
|
+
{{ $addrLen := len $container.Addresses }}
|
129
|
+
|
130
|
+
{{ range $knownNetwork := $CurrentContainer.Networks }}
|
131
|
+
{{ range $containerNetwork := $container.Networks }}
|
132
|
+
{{ if (and (ne $containerNetwork.Name "ingress") (or (eq $knownNetwork.Name $containerNetwork.Name) (eq $knownNetwork.Name "host"))) }}
|
133
|
+
## Can be connected with "{{ $containerNetwork.Name }}" network
|
134
|
+
|
135
|
+
{{/* If only 1 port exposed, use that */}}
|
136
|
+
{{ if eq $addrLen 1 }}
|
137
|
+
{{ $address := index $container.Addresses 0 }}
|
138
|
+
{{ template "upstream" (dict "Container" $container "Address" $address "Network" $containerNetwork) }}
|
139
|
+
{{/* If more than one port exposed, use the one matching VIRTUAL_PORT env var, falling back to standard web port 80 */}}
|
140
|
+
{{ else }}
|
141
|
+
{{ $port := coalesce $container.Env.VIRTUAL_PORT "80" }}
|
142
|
+
{{ $address := where $container.Addresses "Port" $port | first }}
|
143
|
+
{{ template "upstream" (dict "Container" $container "Address" $address "Network" $containerNetwork) }}
|
144
|
+
{{ end }}
|
145
|
+
{{ else }}
|
146
|
+
# Cannot connect to network of this container
|
147
|
+
server 127.0.0.1 down;
|
148
|
+
{{ end }}
|
149
|
+
{{ end }}
|
150
|
+
{{ end }}
|
151
|
+
{{ end }}
|
152
|
+
}
|
153
|
+
|
154
|
+
{{ $default_host := or ($.Env.DEFAULT_HOST) "" }}
|
155
|
+
{{ $default_server := index (dict $host "" $default_host "default_server") $host }}
|
156
|
+
|
157
|
+
{{/* Get the VIRTUAL_PROTO defined by containers w/ the same vhost, falling back to "http" */}}
|
158
|
+
{{ $proto := trim (or (first (groupByKeys $containers "Env.VIRTUAL_PROTO")) "http") }}
|
159
|
+
|
160
|
+
{{/* Get the NETWORK_ACCESS defined by containers w/ the same vhost, falling back to "external" */}}
|
161
|
+
{{ $network_tag := or (first (groupByKeys $containers "Env.NETWORK_ACCESS")) "external" }}
|
162
|
+
|
163
|
+
{{/* Get the HTTPS_METHOD defined by containers w/ the same vhost, falling back to "redirect" */}}
|
164
|
+
{{ $https_method := or (first (groupByKeys $containers "Env.HTTPS_METHOD")) "redirect" }}
|
165
|
+
|
166
|
+
{{/* Get the SSL_POLICY defined by containers w/ the same vhost, falling back to "Mozilla-Intermediate" */}}
|
167
|
+
{{ $ssl_policy := or (first (groupByKeys $containers "Env.SSL_POLICY")) "Mozilla-Intermediate" }}
|
168
|
+
|
169
|
+
{{/* Get the HSTS defined by containers w/ the same vhost, falling back to "max-age=31536000" */}}
|
170
|
+
{{ $hsts := or (first (groupByKeys $containers "Env.HSTS")) "max-age=31536000" }}
|
171
|
+
|
172
|
+
{{/* Get the VIRTUAL_ROOT By containers w/ use fastcgi root */}}
|
173
|
+
{{ $vhost_root := or (first (groupByKeys $containers "Env.VIRTUAL_ROOT")) "/var/www/public" }}
|
174
|
+
|
175
|
+
|
176
|
+
{{/* Get the first cert name defined by containers w/ the same vhost */}}
|
177
|
+
{{ $certName := (first (groupByKeys $containers "Env.CERT_NAME")) }}
|
178
|
+
|
179
|
+
{{/* Get the best matching cert by name for the vhost. */}}
|
180
|
+
{{ $vhostCert := (closest (dir "/etc/nginx/certs") (printf "%s.crt" $host))}}
|
181
|
+
|
182
|
+
{{/* vhostCert is actually a filename so remove any suffixes since they are added later */}}
|
183
|
+
{{ $vhostCert := trimSuffix ".crt" $vhostCert }}
|
184
|
+
{{ $vhostCert := trimSuffix ".key" $vhostCert }}
|
185
|
+
|
186
|
+
{{/* Use the cert specified on the container or fallback to the best vhost match */}}
|
187
|
+
{{ $cert := (coalesce $certName $vhostCert) }}
|
188
|
+
|
189
|
+
{{ $is_https := (and (ne $https_method "nohttps") (ne $cert "") (exists (printf "/etc/nginx/certs/%s.crt" $cert)) (exists (printf "/etc/nginx/certs/%s.key" $cert))) }}
|
190
|
+
|
191
|
+
{{ if $is_https }}
|
192
|
+
|
193
|
+
{{ if eq $https_method "redirect" }}
|
194
|
+
server {
|
195
|
+
server_name {{ $host }};
|
196
|
+
listen 80 {{ $default_server }};
|
197
|
+
{{ if $enable_ipv6 }}
|
198
|
+
listen [::]:80 {{ $default_server }};
|
199
|
+
{{ end }}
|
200
|
+
access_log /var/log/nginx/access.log vhost;
|
201
|
+
return 301 https://$host$request_uri;
|
202
|
+
}
|
203
|
+
{{ end }}
|
204
|
+
|
205
|
+
server {
|
206
|
+
server_name {{ $host }};
|
207
|
+
listen 443 ssl http2 {{ $default_server }};
|
208
|
+
{{ if $enable_ipv6 }}
|
209
|
+
listen [::]:443 ssl http2 {{ $default_server }};
|
210
|
+
{{ end }}
|
211
|
+
access_log /var/log/nginx/access.log vhost;
|
212
|
+
|
213
|
+
{{ if eq $network_tag "internal" }}
|
214
|
+
# Only allow traffic from internal clients
|
215
|
+
include /etc/nginx/network_internal.conf;
|
216
|
+
{{ end }}
|
217
|
+
|
218
|
+
{{ if eq $ssl_policy "Mozilla-Modern" }}
|
219
|
+
ssl_protocols TLSv1.2 TLSv1.3;
|
220
|
+
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
|
221
|
+
{{ else if eq $ssl_policy "Mozilla-Intermediate" }}
|
222
|
+
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
|
223
|
+
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:!DSS';
|
224
|
+
{{ else if eq $ssl_policy "Mozilla-Old" }}
|
225
|
+
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
|
226
|
+
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:DES-CBC3-SHA:HIGH:SEED:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!RSAPSK:!aDH:!aECDH:!EDH-DSS-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA:!SRP';
|
227
|
+
{{ else if eq $ssl_policy "AWS-TLS-1-2-2017-01" }}
|
228
|
+
ssl_protocols TLSv1.2 TLSv1.3;
|
229
|
+
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:AES128-GCM-SHA256:AES128-SHA256:AES256-GCM-SHA384:AES256-SHA256';
|
230
|
+
{{ else if eq $ssl_policy "AWS-TLS-1-1-2017-01" }}
|
231
|
+
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
|
232
|
+
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA';
|
233
|
+
{{ else if eq $ssl_policy "AWS-2016-08" }}
|
234
|
+
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
|
235
|
+
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA';
|
236
|
+
{{ else if eq $ssl_policy "AWS-2015-05" }}
|
237
|
+
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
|
238
|
+
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:DES-CBC3-SHA';
|
239
|
+
{{ else if eq $ssl_policy "AWS-2015-03" }}
|
240
|
+
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
|
241
|
+
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:DHE-DSS-AES128-SHA:DES-CBC3-SHA';
|
242
|
+
{{ else if eq $ssl_policy "AWS-2015-02" }}
|
243
|
+
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
|
244
|
+
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:DHE-DSS-AES128-SHA';
|
245
|
+
{{ end }}
|
246
|
+
|
247
|
+
ssl_prefer_server_ciphers on;
|
248
|
+
ssl_session_timeout 5m;
|
249
|
+
ssl_session_cache shared:SSL:50m;
|
250
|
+
ssl_session_tickets off;
|
251
|
+
|
252
|
+
ssl_certificate /etc/nginx/certs/{{ (printf "%s.crt" $cert) }};
|
253
|
+
ssl_certificate_key /etc/nginx/certs/{{ (printf "%s.key" $cert) }};
|
254
|
+
|
255
|
+
{{ if (exists (printf "/etc/nginx/certs/%s.dhparam.pem" $cert)) }}
|
256
|
+
ssl_dhparam {{ printf "/etc/nginx/certs/%s.dhparam.pem" $cert }};
|
257
|
+
{{ end }}
|
258
|
+
|
259
|
+
{{ if (exists (printf "/etc/nginx/certs/%s.chain.pem" $cert)) }}
|
260
|
+
ssl_stapling on;
|
261
|
+
ssl_stapling_verify on;
|
262
|
+
ssl_trusted_certificate {{ printf "/etc/nginx/certs/%s.chain.pem" $cert }};
|
263
|
+
{{ end }}
|
264
|
+
|
265
|
+
{{ if (and (ne $https_method "noredirect") (ne $hsts "off")) }}
|
266
|
+
add_header Strict-Transport-Security "{{ trim $hsts }}" always;
|
267
|
+
{{ end }}
|
268
|
+
|
269
|
+
{{ if (exists (printf "/etc/nginx/vhost.d/%s" $host)) }}
|
270
|
+
include {{ printf "/etc/nginx/vhost.d/%s" $host }};
|
271
|
+
{{ else if (exists "/etc/nginx/vhost.d/default") }}
|
272
|
+
include /etc/nginx/vhost.d/default;
|
273
|
+
{{ end }}
|
274
|
+
|
275
|
+
root /var/www/public;
|
276
|
+
try_files $uri @application;
|
277
|
+
|
278
|
+
location @application {
|
279
|
+
{{ if eq $proto "uwsgi" }}
|
280
|
+
include uwsgi_params;
|
281
|
+
uwsgi_pass {{ trim $proto }}://{{ trim $upstream_name }};
|
282
|
+
{{ else if eq $proto "fastcgi" }}
|
283
|
+
root {{ trim $vhost_root }};
|
284
|
+
include fastcgi.conf;
|
285
|
+
fastcgi_pass {{ trim $upstream_name }};
|
286
|
+
{{ else }}
|
287
|
+
proxy_pass {{ trim $proto }}://{{ trim $upstream_name }};
|
288
|
+
{{ end }}
|
289
|
+
|
290
|
+
{{ if (exists (printf "/etc/nginx/htpasswd/%s" $host)) }}
|
291
|
+
auth_basic "Restricted {{ $host }}";
|
292
|
+
auth_basic_user_file {{ (printf "/etc/nginx/htpasswd/%s" $host) }};
|
293
|
+
{{ end }}
|
294
|
+
{{ if (exists (printf "/etc/nginx/vhost.d/%s_location" $host)) }}
|
295
|
+
include {{ printf "/etc/nginx/vhost.d/%s_location" $host}};
|
296
|
+
{{ else if (exists "/etc/nginx/vhost.d/default_location") }}
|
297
|
+
include /etc/nginx/vhost.d/default_location;
|
298
|
+
{{ end }}
|
299
|
+
}
|
300
|
+
}
|
301
|
+
|
302
|
+
{{ end }}
|
303
|
+
|
304
|
+
{{ if or (not $is_https) (eq $https_method "noredirect") }}
|
305
|
+
|
306
|
+
server {
|
307
|
+
server_name {{ $host }};
|
308
|
+
listen 80 {{ $default_server }};
|
309
|
+
{{ if $enable_ipv6 }}
|
310
|
+
listen [::]:80 {{ $default_server }};
|
311
|
+
{{ end }}
|
312
|
+
access_log /var/log/nginx/access.log vhost;
|
313
|
+
|
314
|
+
{{ if eq $network_tag "internal" }}
|
315
|
+
# Only allow traffic from internal clients
|
316
|
+
include /etc/nginx/network_internal.conf;
|
317
|
+
{{ end }}
|
318
|
+
|
319
|
+
{{ if (exists (printf "/etc/nginx/vhost.d/%s" $host)) }}
|
320
|
+
include {{ printf "/etc/nginx/vhost.d/%s" $host }};
|
321
|
+
{{ else if (exists "/etc/nginx/vhost.d/default") }}
|
322
|
+
include /etc/nginx/vhost.d/default;
|
323
|
+
{{ end }}
|
324
|
+
|
325
|
+
root /var/www/public;
|
326
|
+
try_files $uri @application;
|
327
|
+
|
328
|
+
location @application {
|
329
|
+
{{ if eq $proto "uwsgi" }}
|
330
|
+
include uwsgi_params;
|
331
|
+
uwsgi_pass {{ trim $proto }}://{{ trim $upstream_name }};
|
332
|
+
{{ else if eq $proto "fastcgi" }}
|
333
|
+
root {{ trim $vhost_root }};
|
334
|
+
include fastcgi.conf;
|
335
|
+
fastcgi_pass {{ trim $upstream_name }};
|
336
|
+
{{ else }}
|
337
|
+
proxy_pass {{ trim $proto }}://{{ trim $upstream_name }};
|
338
|
+
{{ end }}
|
339
|
+
|
340
|
+
{{ if (exists (printf "/etc/nginx/vhost.d/%s_location" $host)) }}
|
341
|
+
include {{ printf "/etc/nginx/vhost.d/%s_location" $host}};
|
342
|
+
{{ else if (exists "/etc/nginx/vhost.d/default_location") }}
|
343
|
+
include /etc/nginx/vhost.d/default_location;
|
344
|
+
{{ end }}
|
345
|
+
}
|
346
|
+
}
|
347
|
+
|
348
|
+
{{ if (and (not $is_https) (exists "/etc/nginx/certs/default.crt") (exists "/etc/nginx/certs/default.key")) }}
|
349
|
+
server {
|
350
|
+
server_name {{ $host }};
|
351
|
+
listen 443 ssl http2 {{ $default_server }};
|
352
|
+
{{ if $enable_ipv6 }}
|
353
|
+
listen [::]:443 ssl http2 {{ $default_server }};
|
354
|
+
{{ end }}
|
355
|
+
access_log /var/log/nginx/access.log vhost;
|
356
|
+
return 500;
|
357
|
+
|
358
|
+
ssl_certificate /etc/nginx/certs/default.crt;
|
359
|
+
ssl_certificate_key /etc/nginx/certs/default.key;
|
360
|
+
}
|
361
|
+
{{ end }}
|
362
|
+
|
363
|
+
{{ end }}
|
364
|
+
{{ end }}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# https://stackoverflow.com/a/21189044 - thanks.
|
2
|
+
function parse_yaml {
|
3
|
+
local prefix=$2
|
4
|
+
local s='[[:space:]]*' w='[a-zA-Z0-9_]*' fs=$(echo @|tr @ '\034')
|
5
|
+
sed -ne "s|^\($s\):|\1|" \
|
6
|
+
-e "s|^\($s\)\($w\)$s:$s[\"']\(.*\)[\"']$s\$|\1$fs\2$fs\3|p" \
|
7
|
+
-e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p" $1 |
|
8
|
+
awk -F$fs '{
|
9
|
+
indent = length($1)/2;
|
10
|
+
vname[indent] = $2;
|
11
|
+
for (i in vname) {if (i > indent) {delete vname[i]}}
|
12
|
+
if (length($3) > 0) {
|
13
|
+
vn=""; for (i=0; i<indent; i++) {vn=(vn)(vname[i])("_")}
|
14
|
+
printf("%s%s%s=\"%s\"\n", "'$prefix'",vn, $2, $3);
|
15
|
+
}
|
16
|
+
}'
|
17
|
+
}
|
18
|
+
|
19
|
+
eval $(parse_yaml ./.orchestration.yml)
|
20
|
+
|
21
|
+
set -u
|
22
|
+
echo -n "$(eval echo \$$1)"
|
@@ -8,7 +8,6 @@ module Orchestration
|
|
8
8
|
ready: :green,
|
9
9
|
create: :green,
|
10
10
|
update: :yellow,
|
11
|
-
identical: :blue,
|
12
11
|
status: :blue,
|
13
12
|
setup: :blue,
|
14
13
|
input: :red,
|
@@ -21,13 +20,22 @@ module Orchestration
|
|
21
20
|
STDOUT.print colorize(desc, output, color_name)
|
22
21
|
end
|
23
22
|
|
24
|
-
def read(message)
|
25
|
-
write(:input, message
|
26
|
-
STDIN.gets.chomp
|
23
|
+
def read(message, default = nil)
|
24
|
+
write(:input, prompt(message, default), nil, false)
|
25
|
+
result = STDIN.gets.chomp.strip
|
26
|
+
return default if result.empty?
|
27
|
+
|
28
|
+
result
|
27
29
|
end
|
28
30
|
|
29
31
|
private
|
30
32
|
|
33
|
+
def prompt(message, default)
|
34
|
+
return "(#{message}): " if default.nil?
|
35
|
+
|
36
|
+
"(#{message}) [#{I18n.t('orchestration.default')}: #{default}]: "
|
37
|
+
end
|
38
|
+
|
31
39
|
def colorize(desc, message, color_name)
|
32
40
|
color = if color_name.nil?
|
33
41
|
COLOR_MAP.fetch(desc)
|
data/orchestration.gemspec
CHANGED
@@ -42,5 +42,6 @@ Gem::Specification.new do |spec|
|
|
42
42
|
spec.add_development_dependency 'rspec-its', '~> 1.2'
|
43
43
|
spec.add_development_dependency 'rubocop', '~> 0.59.2'
|
44
44
|
spec.add_development_dependency 'sqlite3', '~> 1.3'
|
45
|
+
spec.add_development_dependency 'strong_versions', '~> 0.3.1'
|
45
46
|
spec.add_development_dependency 'webmock', '~> 3.4'
|
46
47
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: orchestration
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bob Farrell
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-12-
|
11
|
+
date: 2018-12-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colorize
|
@@ -248,6 +248,20 @@ dependencies:
|
|
248
248
|
- - "~>"
|
249
249
|
- !ruby/object:Gem::Version
|
250
250
|
version: '1.3'
|
251
|
+
- !ruby/object:Gem::Dependency
|
252
|
+
name: strong_versions
|
253
|
+
requirement: !ruby/object:Gem::Requirement
|
254
|
+
requirements:
|
255
|
+
- - "~>"
|
256
|
+
- !ruby/object:Gem::Version
|
257
|
+
version: 0.3.1
|
258
|
+
type: :development
|
259
|
+
prerelease: false
|
260
|
+
version_requirements: !ruby/object:Gem::Requirement
|
261
|
+
requirements:
|
262
|
+
- - "~>"
|
263
|
+
- !ruby/object:Gem::Version
|
264
|
+
version: 0.3.1
|
251
265
|
- !ruby/object:Gem::Dependency
|
252
266
|
name: webmock
|
253
267
|
requirement: !ruby/object:Gem::Requirement
|
@@ -270,12 +284,14 @@ executables:
|
|
270
284
|
- rspec
|
271
285
|
- rubocop
|
272
286
|
- setup
|
287
|
+
- strong_versions
|
273
288
|
extensions: []
|
274
289
|
extra_rdoc_files: []
|
275
290
|
files:
|
276
291
|
- ".gitignore"
|
277
292
|
- ".rspec"
|
278
293
|
- ".rubocop.yml"
|
294
|
+
- ".strong_versions.yml"
|
279
295
|
- ".travis.yml"
|
280
296
|
- Gemfile
|
281
297
|
- Makefile
|
@@ -286,6 +302,7 @@ files:
|
|
286
302
|
- bin/rspec
|
287
303
|
- bin/rubocop
|
288
304
|
- bin/setup
|
305
|
+
- bin/strong_versions
|
289
306
|
- config/locales/en.yml
|
290
307
|
- lib/Rakefile
|
291
308
|
- lib/orchestration.rb
|
@@ -331,7 +348,9 @@ files:
|
|
331
348
|
- lib/orchestration/templates/Dockerfile.erb
|
332
349
|
- lib/orchestration/templates/Makefile.erb
|
333
350
|
- lib/orchestration/templates/entrypoint.sh.erb
|
351
|
+
- lib/orchestration/templates/nginx.tmpl.erb
|
334
352
|
- lib/orchestration/templates/unicorn.rb.erb
|
353
|
+
- lib/orchestration/templates/yaml.bash.erb
|
335
354
|
- lib/orchestration/terminal.rb
|
336
355
|
- lib/orchestration/version.rb
|
337
356
|
- lib/tasks/orchestration.rake
|