Commit 2ddc5b0c authored by Kirill Smelkov's avatar Kirill Smelkov

gitlab: Organize per-instance gitlab work tree

Organize per-instance place for gitlab configuration and work directory.

Unfortunately as GitLab is Ruby-on-Rails application, it is not possible
to keep its code in one place and have multiple separate configuration
sets in different places and start that code for a configuration set -
GitLab and Rails insist to get configuration from relative to source
code tree.

GitLab omnibus "solves" this by having only one configuration set and
having symlinks from code to that only configiration set. In slapos we
can potentially have several instances for one software and thus we
cannot do that.

With such limitations a proper solution would be to bind-mount software
code into instance filesystem namespace close to configuration - that
way the code will be only one and will find proper per-instance config.
Currently we do not have namespaces available on slapos unfortunately,
thus something else is needed.

The workaround I decided to do is this: to clone cloned gitlab
repository from software/ space to instance/ space and adjust it in
instance space. This has the following drawbacks:

    - code is duplicated
    - code becomes read-write, instead of being read-only

but imho it is the most practical thing to do. Another solution could be
to patch GitLab / Rails to remove "config lives in code" assumption, but
the number of places where this needs to be done is really many.

NOTE gems which gitlab uses and which were installed during software
    compilation are not duplicated - they are reused via bundler - via
    pointing BUNDLE_GEMFILE to original location in software.

NOTE2 For instance tasks and also for maintanace convenience we establish
    <instance>/bin/gitlab-* programs, e.g. gitlab-rake, which e.g. for
    gitlab-rake will run rake with correctly loaded gitlab environment -
    like in gitlab-omnibus.

/cc @kazuhiko, @jerome, @jp
parent 0d286c5d
...@@ -7,6 +7,16 @@ ...@@ -7,6 +7,16 @@
parts = parts =
directory directory
# gitlab-<prog>
# ? mailroom
{% set gitlab_progv = 'rails rake unicorn sidekiq' .split() %}
{% for prog in gitlab_progv %}
gitlab-{{ prog }}
{% endfor %}
gitlab-work
gitlab-shell-work
service-postgresql service-postgresql
service-redis service-redis
...@@ -52,10 +62,161 @@ startup = ${:etc}/run ...@@ -52,10 +62,161 @@ startup = ${:etc}/run
service = ${:etc}/service service = ${:etc}/service
promise = ${:etc}/promise promise = ${:etc}/promise
# gitlab: etc/ log/ ...
[gitlab-dir]
recipe = slapos.cookbook:mkdirectory
etc = ${directory:etc}/gitlab
log = ${directory:log}/gitlab
var = ${directory:var}/gitlab
tmp = ${:var}/tmp
uploads = ${:var}/uploads
assets = ${:var}/assets
backup = ${directory:var}/backup
[gitlab-repo-dir]
recipe = slapos.cookbook:mkdirectory
repositories = ${directory:var}/repositories
# gitlab wants it to be drwxrws---
# FIXME setting such mode with :mkdirectory is not possible, because mkdir(2)
# does & 0777 and also there is umask. So we workaround:
[gitlab-repo-xdir]
recipe = plone.recipe.command
stop-on-error = yes
repositories = ${gitlab-repo-dir:repositories}
command = chmod 02770 ${:repositories}
[gitlab]
etc = ${gitlab-dir:etc}
log = ${gitlab-dir:log}
var = ${gitlab-dir:var}
tmp = ${gitlab-dir:tmp}
uploads = ${gitlab-dir:uploads}
assets = ${gitlab-dir:assets}
backup = ${gitlab-dir:backup}
repositories = ${gitlab-repo-xdir:repositories}
# gitlab-shell: etc/ log/ gitlab_shell_secret ...
[gitlab-shell-dir]
recipe = slapos.cookbook:mkdirectory
etc = ${directory:etc}/gitlab-shell
log = ${directory:log}/gitlab-shell
[gitlab-shell]
etc = ${gitlab-shell-dir:etc}
log = ${gitlab-shell-dir:log}
secret = ${secrets:secrets}/gitlab_shell_secret
# 2. services
# place to keep all secrets
[secrets]
recipe = slapos.cookbook:mkdirectory
secrets = ${directory:var}/secrets
mode = 0700
# 2. bin/
# gitlab-<prog>
[gitlab-bin]
recipe = slapos.cookbook:wrapper
wrapper-path = ${directory:bin}/${:_buildout_section_name_}
environment =
BUNDLE_GEMFILE = {{ gitlab_repository_location }}/Gemfile
RAILS_ENV = production
# NOTE sys.argv[1:] implicitly appended
# (by slapos.recipe.librecipe.execute.generic_exec() at runtime)
command-line =
{{ bundler_4gitlab }} exec sh -c
'cd ${gitlab-work:location} && ${:prog} "$@"' ${:prog}
{% for prog in gitlab_progv %}
[gitlab-{{ prog }}]
<= gitlab-bin
prog = {{ prog }}
{% endfor %}
# 3. gitlab- & gitlab-shell- work directories
#
# Gitlab/Rails operation is tightened that config/ lives inside code, which goes
# against having ability to create several instances configured differently
# from 1 SR.
#
# One possibility to overcome this could be to make another Gitlab root
# symbolically linked to original SR _and_ several configuration files
# symbolically linked to instance place. Unfortunately this does not work -
# Ruby determines realpath on module import and Gitlab and Rails lookup config
# files relative to imported modules.
#
# we clone cloned gitlab and add proper links to vendor/bundle and instance
# config files.
# XXX there is no need for full clone - we only need worktree checkout (a-la `git
# worktree add`, but without creating files in original clone)
#
# This way Gitlab/Rails still think they work in 1 code / 1 instance way,
# and we can reuse SR.
# XXX better do such tricks with bind mounting, but that requires user namespaces
[work-base]
recipe = plone.recipe.command
stop-on-error = yes
location = ${directory:home}/${:_buildout_section_name_}
command =
# make sure we start from well-defined empty state
# (needed e.g. if previous install failed in the middle)
rm -rf ${:location} &&
# init work repository and add `software` remote pointing to main repo in SR software/...
{{ git }} init ${:location} &&
cd ${:location} &&
{{ git }} remote add software ${:software} &&
${:update-command}
update-command =
cd ${:location} &&
{{ git }} fetch software &&
{{ git }} reset --hard `cd ${:software} && {{ git }} rev-parse HEAD` &&
${:tune-command}
# NOTE there is no need to link/create .gitlab_shell_secret - we will set path to it
# in gitlab & gitlab-shell configs, and gitlab creates it on its first start
[gitlab-work]
<= work-base
software = {{ gitlab_repository_location }}
tune-command =
# secret* tmp/ log/
rm -f .secret &&
rm -rf log tmp &&
ln -sf ${secrets:secrets}/gitlab_rails_secret .secret &&
ln -sf ${gitlab:log} log &&
ln -sf ${gitlab:tmp} tmp &&
# config/
cd config &&
ln -sf ${secrets:secrets}/gitlab_secrets.yml secrets.yml &&
# public/
cd ../public &&
rm -rf uploads assets &&
ln -sf ${gitlab:uploads} uploads &&
ln -sf ${gitlab:assets} assets &&
true
# ----//---- for gitlab-shell
[gitlab-shell-work]
<= work-base
software = {{ gitlab_shell_repository_location }}
tune-command =
true
# 4. services
# [promise-<something>] to generate promise wrapper <something> # [promise-<something>] to generate promise wrapper <something>
[promise-wrapper] [promise-wrapper]
......
...@@ -22,9 +22,13 @@ rendered= $${buildout:directory}/instance-gitlab.cfg ...@@ -22,9 +22,13 @@ rendered= $${buildout:directory}/instance-gitlab.cfg
context = context =
key eggs_directory buildout:eggs-directory key eggs_directory buildout:eggs-directory
key develop_eggs_directory buildout:develop-eggs-directory key develop_eggs_directory buildout:develop-eggs-directory
raw gitlab_repository_location ${gitlab-repository:location}
raw gitlab_shell_repository_location ${gitlab-shell-repository:location}
# program binaries # program binaries
raw bundler_4gitlab ${bundler-4gitlab:bundle}
raw dcron_bin ${dcron-output:crond} raw dcron_bin ${dcron-output:crond}
raw git ${git:location}/bin/git
raw gunzip_bin ${gzip:location}/bin/gunzip raw gunzip_bin ${gzip:location}/bin/gunzip
raw gzip_bin ${gzip:location}/bin/gzip raw gzip_bin ${gzip:location}/bin/gzip
raw logrotate_bin ${logrotate:location}/usr/sbin/logrotate raw logrotate_bin ${logrotate:location}/usr/sbin/logrotate
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment