diff options
author | Toon Claes <toon@gitlab.com> | 2019-05-28 14:39:02 +0300 |
---|---|---|
committer | Toon Claes <toon@gitlab.com> | 2019-07-01 14:40:21 +0300 |
commit | 6f9a42160ae70fa53a384fc9a61a1d65c16791d7 (patch) | |
tree | 62f668949bd98cb6034d52f21da4bcca74849029 | |
parent | 8464bb690b02e63dfd2bcf49a7eb345ad5a31bf7 (diff) |
Convert defaults file into ruby code
Instead of crazy tricks with ERB in YAML, define the config directly
in ruby.
With method_missing we're dynamically generating methods of each of
the settings. These settings follow the same structure of the YAML
file people can use to override their settings.
So the settings are applied as following:
- from gdk.yml
- from lose files like: hostname, port, webpack_port, etc.
- from defaults defined in lib/gdk/config.rb directly
-rw-r--r-- | Procfile.erb | 17 | ||||
-rw-r--r-- | Rakefile | 4 | ||||
-rw-r--r-- | lib/gdk/config.rb | 126 | ||||
-rw-r--r-- | lib/gdk/config_settings.rb | 89 |
4 files changed, 212 insertions, 24 deletions
diff --git a/Procfile.erb b/Procfile.erb index a1beea0c9dc..51d1f3d753c 100644 --- a/Procfile.erb +++ b/Procfile.erb @@ -14,20 +14,20 @@ postgresql: exec support/postgresql-signal-wrapper <%= config.postgresql.bin_dir # Geo # -<%= '#' unless config.geo.enabled %>postgresql-geo: exec support/postgresql-signal-wrapper <%= config.postgresql.bin_dir %>/postgres -D <%= config.postgresql.geo_dir %>/data -k <%= config.postgresql.geo_dir %> -h '' -<%= '#' unless config.geo.enabled %>geo-cursor: exec /usr/bin/env RAILS_ENV=development RAILS_RELATIVE_URL_ROOT=$relative_url_root support/geo-logcursor +<%= '#' unless config.geo? %>postgresql-geo: exec support/postgresql-signal-wrapper <%= config.postgresql.bin_dir %>/postgres -D <%= config.postgresql.geo_dir %>/data -k <%= config.postgresql.geo_dir %> -h '' +<%= '#' unless config.geo? %>geo-cursor: exec /usr/bin/env RAILS_ENV=development RAILS_RELATIVE_URL_ROOT=$relative_url_root support/geo-logcursor # Backend services # gitaly: exec gitaly/bin/gitaly <%= config.gdk_root %>/gitaly/config.toml -gitlab-workhorse: exec /usr/bin/env PATH="<%= config.gdk_root %>/gitlab-workhorse/bin:$PATH" gitlab-workhorse -authSocket <%= config.gdk_root %>/gitlab.socket -listenAddr $host:<%= config.nginx.enabled ? config.nginx.workhorse_port : '$port' %> -documentRoot <%= config.gdk_root %>/gitlab/public -developmentMode -secretPath <%= config.gdk_root %>/gitlab/.gitlab_workhorse_secret -config <%= config.gdk_root %>/gitlab-workhorse/config.toml +gitlab-workhorse: exec /usr/bin/env PATH="<%= config.gdk_root %>/gitlab-workhorse/bin:$PATH" gitlab-workhorse -authSocket <%= config.gdk_root %>/gitlab.socket -listenAddr $host:<%= config.nginx? ? config.nginx.workhorse_port : '$port' %> -documentRoot <%= config.gdk_root %>/gitlab/public -developmentMode -secretPath <%= config.gdk_root %>/gitlab/.gitlab_workhorse_secret -config <%= config.gdk_root %>/gitlab-workhorse/config.toml rails-background-jobs: exec /usr/bin/env SIDEKIQ_LOG_ARGUMENTS=1 RAILS_ENV=development RAILS_RELATIVE_URL_ROOT=$relative_url_root support/exec-cd gitlab bin/background_jobs start_foreground # Frontend services # webpack: exec /usr/bin/env NODE_ENV=development DEV_SERVER_PORT=<%= config.webpack.port %> DEV_SERVER_HOST=$host support/exec-cd gitlab yarn dev-server rails-web: exec /usr/bin/env RAILS_ENV=development RAILS_RELATIVE_URL_ROOT=$relative_url_root support/exec-cd gitlab bin/web start_foreground -<%= '#' unless config.gitlab_pages.enabled %>gitlab-pages: exec gitlab-pages/bin/gitlab-pages -listen-http ":<%= config.gitlab_pages.port %>" -artifacts-server <%= config.https ? 'https' : 'http' %>://<%= config.hostname %>:<%= config.port %>/api/v4 -pages-root <%= config.gdk_root %>/gitlab/shared/pages/ -pages-domain 127.0.0.1.xip.io +<%= '#' unless config.gitlab_pages? %>gitlab-pages: exec gitlab-pages/bin/gitlab-pages -listen-http ":<%= config.gitlab_pages.port %>" -artifacts-server <%= config.https ? 'https' : 'http' %>://<%= config.hostname %>:<%= config.port %>/api/v4 -pages-root <%= config.gdk_root %>/gitlab/shared/pages/ -pages-domain 127.0.0.1.xip.io # Docker # @@ -38,16 +38,15 @@ registry: exec support/docker-registry #influxdb: exec influxdb/bin/influxd -config influxdb/influxdb.conf #grafana: exec support/wait-postgresql-ready support/exec-cd grafana bin/grafana-server -config grafana.ini #prometheus: exec docker run --net host -p 9090:9090 -v <%= config.gdk_root %>/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus:v2.8.1 - -<%= '#' unless config.tracer.jaeger.enabled %>jaeger: exec jaeger/jaeger-<%= config.tracer.jaeger.version %>/jaeger-all-in-one --memory.max-traces 512 +<%= '#' unless config.tracer.jaeger? %>jaeger: exec jaeger/jaeger-<%= config.tracer.jaeger.version %>/jaeger-all-in-one --memory.max-traces 512 # Additional services # #sshd: exec <%= config.sshd.bin %> -e -D -f <%= config.gdk_root %>/openssh/sshd_config -<%= '#' unless config.nginx.enabled %>nginx: exec <%= config.nginx.bin %> -p <%= config.gdk_root %>/nginx -c conf/nginx.conf +<%= '#' unless config.nginx? %>nginx: exec <%= config.nginx.bin %> -p <%= config.gdk_root %>/nginx -c conf/nginx.conf #elasticsearch: exec elasticsearch/bin/elasticsearch # Tunneling # -<%= '#' unless config.auto_devops.enabled %>tunnel_gitlab: ssh -N -R $auto_devops_gitlab_port:localhost:$port qa-tunnel.gitlab.info -<%= '#' unless config.auto_devops.enabled %>tunnel_registry: ssh -N -R $auto_devops_registry_port:localhost:5000 qa-tunnel.gitlab.info +<%= '#' unless config.auto_devops? %>tunnel_gitlab: ssh -N -R $auto_devops_gitlab_port:localhost:$port qa-tunnel.gitlab.info +<%= '#' unless config.auto_devops? %>tunnel_registry: ssh -N -R $auto_devops_registry_port:localhost:5000 qa-tunnel.gitlab.info @@ -8,10 +8,10 @@ def config @config ||= GDK::Config.new end -file 'Procfile' => ['Procfile.erb', GDK::Config::FILE, GDK::Defaults::FILE] do |t| +file 'Procfile' => ['Procfile.erb', GDK::Config::FILE] do |t| GDK::ErbRenderer.new(t.source, t.name).safe_render! end -file 'nginx/conf/nginx.conf' => ['nginx/conf/nginx.conf.erb', GDK::Config::FILE, GDK::Defaults::FILE] do |t| +file 'nginx/conf/nginx.conf' => ['nginx/conf/nginx.conf.erb', GDK::Config::FILE] do |t| GDK::ErbRenderer.new(t.source, t.name).safe_render! end diff --git a/lib/gdk/config.rb b/lib/gdk/config.rb index 91f7e895e7b..f65df324ad9 100644 --- a/lib/gdk/config.rb +++ b/lib/gdk/config.rb @@ -1,29 +1,129 @@ # frozen_string_literal: true -require_relative 'config_file' -require_relative 'defaults' +require_relative 'config_settings' module GDK - class Config < ConfigFile + class Config < ConfigSettings FILE = 'gdk.yml' - def initialize - super(FILE) + repositories do |r| + r.gitlab 'https://gitlab.com/gitlab-org/gitlab-ce.git' + r.gitlab_shell 'https://gitlab.com/gitlab-org/gitlab-shell.git' + r.gitlab_workhorse 'https://gitlab.com/gitlab-org/gitlab-workhorse.git' + r.gitaly 'https://gitlab.com/gitlab-org/gitaly.git' + r.gitaly_proto 'https://gitlab.com/gitlab-org/gitaly-proto.git' + r.gitlab_pages 'https://gitlab.com/gitlab-org/gitlab-pages.git' + r.gitlab_docs 'https://gitlab.com/gitlab-com/gitlab-docs.git' end - def defaults - @defaults ||= Defaults.new + gdk_root { cmd!('pwd') } + + hostname do + next "#{config.auto_devops.gitlab.port}.qa-tunnel.gitlab.info" if config.auto_devops.enabled + read!('hostname') || 'localhost' + end + + port do + next 443 if config.auto_devops.enabled + read!('port') || 3000 + end + + https do + next true if config.auto_devops.enabled + read!('https_enabled') || false + end + + relative_url_root { read!('relative_url_root') || nil } + username { cmd!('whoami') } + + webpack do |w| + w.port { read!('webpack_port') || 3808 } + end + + registry do |r| + r.enabled do + next true if config.auto_devops.enabled + read!('registry_enabled') || false + end + + r.host do + next "#{config.auto_devops.registry.port}.qa-tunnel.gitlab.info" if config.auto_devops.enabled + '127.0.0.1' + end + + r.port do + next config.auto_devops.registry.port if config.auto_devops.enabled + read!('registry_port') || 5000 + end + + r.external_port do + next 443 if config.auto_devops.enabled + 5000 + end + end + + object_store do |o| + o.enabled { read!('object_store_enabled') || false } + o.port { read!('object_store_port') || 9000 } end - def respond_to_missing?(method_name, *_args) - config.respond_to?(method_name) || defaults.respond_to?(method_name) || super + gitlab_pages do |p| + p.enabled true + p.port { read!('gitlab_pages_port') || 3010 } end - def method_missing(method_name, *_args, &_block) - return config[method_name] if config.respond_to?(method_name) - return defaults.config[method_name] if defaults.respond_to?(method_name) + auto_devops do |a| + a.enabled { read!('auto_devops_enabled') || false } + a.gitlab do |g| + g.port { read_or_write!('auto_devops_gitlab_port', rand(20000..24999)) } + end + a.registry do |r| + r.port { read!('auto_devops_registry_port') || (config.auto_devops.gitlab.port + 5000) } + end + end + + geo do |g| + g.enabled false + end + + elasticsearch do |e| + e.version '6.5.1' + e.checksum '5903e1913a7c96aad96a8227517c40490825f672' + end + + tracer do |t| + t.build_tags 'tracer_static tracer_static_jaeger' + t.jaeger do |j| + j.enabled true + j.version '1.10.1' + end + end + + nginx do |n| + n.enabled false + n.bin { cmd!('which nginx') } + n.workhorse_port 3333 + end + + postgresql do |p| + p.bin_dir { cmd!('support/pg_bindir') } + p.replication_user 'gitlab_replication' + p.dir { "#{config.gdk_root}/postgresql" } + p.data_dir { "#{config.postgresql.dir}/data" } + p.replica_dir { "#{config.gdk_root}/postgresql-replica" } + p.geo_dir { "#{config.gdk_root}/postgresql-geo" } + end + + gitaly do |g| + g.assembly_dir { "#{config.gdk_root}/gitaly/assembly" } + end + + sshd do |s| + s.bin { cmd!('which sshd') } + end - super + git do |g| + g.bin { cmd!('which git') } end end end diff --git a/lib/gdk/config_settings.rb b/lib/gdk/config_settings.rb new file mode 100644 index 00000000000..7b13f771d26 --- /dev/null +++ b/lib/gdk/config_settings.rb @@ -0,0 +1,89 @@ +# frozen_string_literal: true + +require 'yaml' + +module GDK + class ConfigSettings + SettingUndefined = Class.new(StandardError) + + attr_accessor :parent, :yaml + + def self.method_missing(name, *args, &blk) + if !args.empty? + define_method(name) do + yaml.fetch(name.to_s, args.first) + end + elsif block_given? + define_method(name) do + # return the result of the block if it didn't take an argument + # otherwise return an instance of the sub ConfigSettings + return yaml.fetch(name.to_s, instance_eval(&blk)) if blk.arity.zero? + + sub = Class.new(ConfigSettings) + blk.call(sub) + sub.new(parent: self, yaml: yaml[name.to_s]) + end + else + raise SettingUndefined, "Could not find the setting '#{name}'" + end + end + + # Provide a shorter form for `config.setting.enabled` as `config.setting?` + def method_missing(name, *args, &blk) + return super unless name.to_s.end_with?('?') + setting = name.to_s.chop.to_sym + + return super unless respond_to?(setting) && public_send(setting).respond_to?(:enabled) + + public_send(setting).enabled + end + + def cmd!(cmd) + `#{cmd}`.chomp + end + + def read!(filename) + sanitized_read!(filename) + rescue Errno::ENOENT + nil + end + + def read_or_write!(filename, value) + sanitized_read!(filename) + rescue Errno::ENOENT + File.write(filename, value) + value + end + + def initialize(parent: nil, yaml: nil) + @parent = parent + @yaml = yaml || load_yaml! + end + + def root + parent&.root || self + end + alias_method :config, :root + + private + + def load_yaml! + return {} unless defined?(self.class::FILE) + + @yaml = YAML.load_file(self.class::FILE) + end + + def from_yaml(key, default: nil) + yaml.has_key?(key) ? yaml[key] : default + end + + def sanitized_read!(filename) + value = File.read(filename).chomp + + return true if value == "true" + return false if value == "false" + return value.to_i if value == value.to_i.to_s + value + end + end +end |