diff --git a/.docker/base/Dockerfile.base b/.docker/base/Dockerfile.base new file mode 100644 index 000000000..709809aed --- /dev/null +++ b/.docker/base/Dockerfile.base @@ -0,0 +1,106 @@ +FROM debian:stretch + +RUN echo "deb http://archive.debian.org/debian stretch main" > /etc/apt/sources.list +RUN echo "deb http://archive.debian.org/debian-security stretch/updates main" >> /etc/apt/sources.list + +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + bzip2 \ + ca-certificates \ + libffi-dev \ + libgdbm3 \ + libssl1.0-dev \ + libyaml-dev \ + procps \ + zlib1g-dev \ + && rm -rf /var/lib/apt/lists/* + +# skip installing gem documentation +RUN mkdir -p /usr/local/etc \ + && { \ + echo 'install: --no-document'; \ + echo 'update: --no-document'; \ + } >> /usr/local/etc/gemrc + +ENV RUBY_MAJOR 2.1 +ENV RUBY_VERSION 2.1.10 +ENV RUBY_DOWNLOAD_SHA256 5be9f8d5d29d252cd7f969ab7550e31bbb001feb4a83532301c0dd3b5006e148 +ENV RUBYGEMS_VERSION 2.6.12 +ENV BUNDLER_VERSION 1.15.1 + +# some of ruby's build scripts are written in ruby +# we purge system ruby later to make sure our final image uses what we just built +RUN set -ex \ + \ + && buildDeps=' \ + autoconf \ + bison \ + dpkg-dev \ + gcc \ + libbz2-dev \ + libgdbm-dev \ + libglib2.0-dev \ + libncurses-dev \ + libreadline-dev \ + libxml2-dev \ + libxslt-dev \ + make \ + ruby \ + wget \ + xz-utils \ + ' \ + && apt-get update \ + && apt-get install -y --no-install-recommends $buildDeps \ + && rm -rf /var/lib/apt/lists/* \ + \ + && wget -O ruby.tar.xz "https://cache.ruby-lang.org/pub/ruby/${RUBY_MAJOR%-rc}/ruby-$RUBY_VERSION.tar.xz" \ + && echo "$RUBY_DOWNLOAD_SHA256 *ruby.tar.xz" | sha256sum -c - \ + \ + && mkdir -p /usr/src/ruby \ + && tar -xJf ruby.tar.xz -C /usr/src/ruby --strip-components=1 \ + && rm ruby.tar.xz \ + \ + && cd /usr/src/ruby \ + \ +# hack in "ENABLE_PATH_CHECK" disabling to suppress: +# warning: Insecure world writable dir + && { \ + echo '#define ENABLE_PATH_CHECK 0'; \ + echo; \ + cat file.c; \ + } > file.c.new \ + && mv file.c.new file.c \ + \ + && autoconf \ + && gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)" \ + && ./configure \ + --build="$gnuArch" \ + --disable-install-doc \ + --enable-shared \ + && make -j "$(nproc)" \ + && make install \ + \ + && dpkg-query --show --showformat '${package}\n' \ + | grep -P '^libreadline\d+$' \ + | xargs apt-mark manual \ + && apt-get purge -y --auto-remove $buildDeps \ + && cd / \ + && rm -r /usr/src/ruby \ + \ + && gem update --system "$RUBYGEMS_VERSION" \ + && gem install bundler --version "$BUNDLER_VERSION" --force \ + && rm -r /root/.gem/ + +# install things globally, for great justice +# and don't create ".bundle" in all our apps +ENV GEM_HOME /usr/local/bundle +ENV BUNDLE_PATH="$GEM_HOME" \ + BUNDLE_SILENCE_ROOT_WARNING=1 \ + BUNDLE_APP_CONFIG="$GEM_HOME" +# path recommendation: https://github.com/bundler/bundler/pull/6469#issuecomment-383235438 +ENV PATH $GEM_HOME/bin:$BUNDLE_PATH/gems/bin:$PATH +# adjust permissions of a few directories for running "gem install" as an arbitrary user +RUN mkdir -p "$GEM_HOME" && chmod 777 "$GEM_HOME" +# (BUNDLE_PATH = GEM_HOME, no need to mkdir/chown both) + +CMD [ "irb" ] \ No newline at end of file diff --git a/.docker/config/database.rb b/.docker/config/database.rb new file mode 100644 index 000000000..b3895a069 --- /dev/null +++ b/.docker/config/database.rb @@ -0,0 +1,9 @@ +require File.join(File.dirname(__FILE__), "..", "lib/ojdbc7-12.1.0.2.0.jar") +Sequel::Model.plugin(:schema) +Sequel::Model.raise_on_save_failure = false # Do not throw exceptions on failure +Sequel::Model.db = case Padrino.env + when :development then Sequel.connect("B2B_URI") + when :production then Sequel.connect("B2B_URI") + when :test then Sequel.connect("B2B_URI") + when :cte then Sequel.connect("B2B_URI") +end diff --git a/.docker/config/glue_update.sh b/.docker/config/glue_update.sh new file mode 100644 index 000000000..6733e828f --- /dev/null +++ b/.docker/config/glue_update.sh @@ -0,0 +1,234 @@ +#!/bin/bash -xe +#set -e +## Global Vars + +cd /edidb + +if [ -z "$1" ] +then + DAYS=2 +else + DAYS=$1 +fi + +export START_DATE=`date --date="$DAYS days ago" +%Y%m%d000000` +export ENV_NAME +export HBX_ID +export EDIDB_DB_HOST +export EDIDB_DB_NAME +export EDIDB_DB_PASSWORD +export B2B_HOST +export B2B_SERVICE_PASSWORD +export SLACK_TOKEN +export SLACK_CHANNEL +export TO_ADDRESSES +export EMAIL_FROM_ADDRESS +export EDIDB_CURL_URL +export RABBITMQ_CURL_URL +export RABBITMQ_USER +export RABBITMQ_PASSWORD +export AWS_ACCESS_KEY_ID +export AWS_SECRET_ACCESS_KEY +export REPORT_ZIP_PASSWORD + +## notification function +function send_sms_notification +{ +cat << EOH > sms_notification.rb +#!/usr/bin/env ruby + +require 'active_resource' +require 'json' +require 'aws-sdk' + +ses = Aws::SES::Client.new( + region: 'us-east-1', + access_key_id: ENV['AWS_ACCESS_KEY_ID'], + secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'] +) + +date = Time.now.inspect +email_subject = "GlueDB Update $1 \n\n" +email_body = "\n$1 at: \n#{date}\n\n$2" + + +resp = ses.send_email({ + source: ENV['EMAIL_FROM_ADDRESS'], + destination: { + to_addresses: ENV.fetch('TO_ADDRESSES').split(',') + }, + message: { + subject: { + data: email_subject + }, + body: { + text: { + data: email_body + } + }, + }, + reply_to_addresses: ENV.fetch('EMAIL_FROM_ADDRESS').split(','), +}) + +EOH + +ruby ./sms_notification.rb + +} + +## slack message to note the beginning of the glue update +curl -X POST -H "Content-type: application/json; charset=utf-8" -H "Authorization: Bearer ${SLACK_TOKEN}" --data '{"channel": "#SLACK_CHANNEL", "username": "EDI Database Bot", "text": "'\`' ### GlueDB Update Started ### '\`'", "icon_emoji": ":gear:"}' https://slack.com/api/chat.postMessage + +cat > script.sh <<'EOL' +#!/bin/bash -xe + +##App Server Vars +export PARSER_DIRECTORY='/edidb/ediparser' +export GLUEDB_DIRECTORY='/edidb' +export UPDATER_DIRECTORY='/edidb/hbx_oracle' +export START_DATE + +##cleanup files +rm -f ${GLUEDB_DIRECTORY}/todays_data.zip +rm -f ${GLUEDB_DIRECTORY}/db/data/all_json.csv +rm -f ${PARSER_DIRECTORY}/*.csv +rm -f ${UPDATER_DIRECTORY}/*.csv + +cat << EOH > /edidb/gateway_transmissions.sh +unset BUNDLE_APP_CONFIG +unset BUNDLE_BIN +unset BUNDLE_PATH +unset BUNDLER_VERSION +unset GEM_HOME +unset RUBYGEMS_VERSION +PATH=/edidb/jruby-1.7.27/bin:$PATH +GEM_PATH=/edidb/jruby-1.7.27/lib/ruby/gems/shared +cd ${UPDATER_DIRECTORY} +padrino r scripts/gateway_transmissions.rb --start $START_DATE +EOH + +chmod 744 /edidb/gateway_transmissions.sh + +set +e +batch_handler=$( kubectl get pods | grep edidb-glue-batch | grep Running ) +set -e +if [ -z "$batch_handler" ]; then + kubectl patch cronjobs edidb-glue-batch -p "{\"spec\" : {\"suspend\" : true }}" + curl -X POST -H "Content-type: application/json; charset=utf-8" -H "Authorization: Bearer ${SLACK_TOKEN}" --data '{"channel": "#'$SLACK_CHANNEL'", "username": "EDI Database Bot", "text": "'\`' ### GlueDB Update Started ### '\`'", "icon_emoji": ":gear:"}' https://slack.com/api/chat.postMessage +else + exit 5 +fi + + +## bring down the listeners +echo "bringing down listeners: "$(date) +kubectl scale --replicas=0 deployment/edidb-enrollment-validator deployment/edidb-broker-updated-listener \ + deployment/edidb-policy-id-list-listener deployment/edidb-enrollment-event-listener \ + deployment/edidb-enrollment-event-handler deployment/edidb-enrollment-event-batch-processor +sleep 60 +kubectl scale --replicas=0 deployment/edidb-enroll-query-result-handler +sleep 120 +kubectl scale --replicas=0 deployment/edidb-employer-workers +sleep 120 +kubectl scale --replicas=0 deployment/edidb-legacy-listeners +sleep 180 + +echo "copying prod databaase: "$(date) +mongo --host $EDIDB_DB_HOST --authenticationDatabase 'admin' -u 'admin' -p $EDIDB_DB_PASSWORD < ~/scripts/prepare_dev.js + +sleep 10 + +/edidb/gateway_transmissions.sh +cp ${UPDATER_DIRECTORY}/b2b_edi.csv ${PARSER_DIRECTORY} +cat ${PARSER_DIRECTORY}/b2b_edi.csv | ${PARSER_DIRECTORY}/dist/build/InterchangeTest/InterchangeTest > ${PARSER_DIRECTORY}/all_json.csv +mkdir -p ${GLUEDB_DIRECTORY}/db/data +cp ${PARSER_DIRECTORY}/all_json.csv ${GLUEDB_DIRECTORY}/db/data/ + +cd ${GLUEDB_DIRECTORY} +#echo -e '\ngem "rubycritic"' >> Gemfile +#bundle install +RAILS_ENV=development bundle exec rake edi:import:all +RAILS_ENV=development rails r script/queries/set_authority_members.rb +#head -n -1 Gemfile > Gemfile.tmp +#mv Gemfile.tmp Gemfile + +echo "updating prod database: "$(date) +update=`mongo --host $EDIDB_DB_HOST --authenticationDatabase 'admin' -u 'admin' -p $EDIDB_DB_PASSWORD < ~/scripts/prepare_prod.js` +echo $update +update=$(echo -n ${update#*"db ${EDIDB_DB_NAME}_dev"}) +update=$(echo -n ${update%bye*}) +update=$(echo -n ${update#*clone}) +update_status=`echo $update | python -c 'import json,sys;obj=json.load(sys.stdin);print obj["'ok'"]'` + +sleep 60 + +if [ "$update_status" -eq 1 ]; then + + #curl -X POST -H "Content-type: application/json; charset=utf-8" -H "Authorization: Bearer ${SLACK_TOKEN}" --data '{"channel": "#'$SLACK_CHANNEL'", "username": "EDI Database Bot", "text": "'\`' ### GlueDB Update Completed :: Running Reports Before Starting Listeners ### '\`'", "icon_emoji": ":gear:"}' https://slack.com/api/chat.postMessage + + #cp /etc/reports/glue_enrollment_report.sh /edidb/glue_enrollment_report.sh && chmod 744 /edidb/glue_enrollment_report.sh + #cp /etc/reports/glue_enrollment_report.json.template /edidb/glue_enrollment_report.json.template + #/edidb/glue_enrollment_report.sh > glue_enrollment_report.log + #tail -30 glue_enrollment_report.log + + #cp /etc/reports/policies_missing_transmissions.sh /edidb/policies_missing_transmissions.sh && chmod 744 /edidb/policies_missing_transmissions.sh + #cp /etc/reports/policies_missing_transmissions.json.template /edidb/policies_missing_transmissions.json.template + #/edidb/policies_missing_transmissions.sh > policies_missing_transmissions.log + #tail -10 policies_missing_transmissions.log + + kubectl scale --replicas=1 deployment/edidb-legacy-listeners + messages=1 + while [ $messages -gt 0 ] + do + sleep 120 + messages=$( curl --user $RABBITMQ_USER:$RABBITMQ_PASSWORD $RABBITMQ_CURL_URL/api/queues/%2F/$HBX_ID.$ENV_NAME.q.glue.individual_updated_listener | jq .messages | tail -1 ) + done + kubectl scale --replicas=1 deployment/edidb-employer-workers + sleep 120 + kubectl scale --replicas=2 deployment/edidb-enroll-query-result-handler + sleep 120 + kubectl scale --replicas=2 deployment/edidb-enrollment-validator deployment/edidb-broker-updated-listener \ + deployment/edidb-policy-id-list-listener deployment/edidb-enrollment-event-listener \ + deployment/edidb-enrollment-event-handler \ + deployment/edidb-enrollment-event-batch-processor + sleep 120 + kubectl patch cronjobs edidb-glue-batch -p "{\"spec\" : {\"suspend\" : false }}" + kubectl rollout restart deployment edidb-$ENV_NAME +else + exit 1 +fi + +EOL + +chmod +x script.sh +set +e +./script.sh +update_status=$? +set -e +sleep 120 + +curlTestCmd="curl -sLk -w "%{http_code}" -o /dev/null ${EDIDB_CURL_URL}/accounts/sign_in" +curlTest=`eval $curlTestCmd` + +if [ "$update_status" -eq 0 ] +then + if [ "$curlTest" == "200" ] + then + curl -X POST -H "Content-type: application/json; charset=utf-8" -H "Authorization: Bearer ${SLACK_TOKEN}" --data '{"channel": "#'$SLACK_CHANNEL'", "username": "EDI Database Bot", "text": "'\`' ### GlueDB Update Completed :: Listeners Are Up ### '\`'", "icon_emoji": ":gear:"}' https://slack.com/api/chat.postMessage + send_sms_notification Success + exit 0 + else + curl -X POST -H "Content-type: application/json; charset=utf-8" -H "Authorization: Bearer ${SLACK_TOKEN}" --data '{"channel": "#'$SLACK_CHANNEL'", "username": "EDI Database Bot", "text": "'\`' ### GlueDB Update Completed :: But Restart Failed ### '\`'", "icon_emoji": ":gear:"}' https://slack.com/api/chat.postMessage + send_sms_notification "Restart Failed" + exit 1 + fi +elif [ "$update_status" -eq 5 ] +then + curl -X POST -H "Content-type: application/json; charset=utf-8" -H "Authorization: Bearer ${SLACK_TOKEN}" --data '{"channel": "#'$SLACK_CHANNEL'", "username": "EDI Database Bot", "text": " '\`' ### GlueDB Update Did Not Start -- Batch Handler Is Running ### '\`'", "icon_emoji": ":gear:"}' https://slack.com/api/chat.postMessage + send_sms_notification "Did Not Start" "The batch handler is running!" + exit 1 +else + curl -X POST -H "Content-type: application/json; charset=utf-8" -H "Authorization: Bearer ${SLACK_TOKEN}" --data '{"channel": "#'$SLACK_CHANNEL'", "username": "EDI Database Bot", "text": " '\`' ### GlueDB Update Failed ### '\`'", "icon_emoji": ":gear:"}' https://slack.com/api/chat.postMessage + send_sms_notification Failed "Please check GlueDB Update job in ${ENV_NAME}" + exit 1 +fi diff --git a/.docker/config/prepare_dev.js b/.docker/config/prepare_dev.js new file mode 100644 index 000000000..f8aac20fb --- /dev/null +++ b/.docker/config/prepare_dev.js @@ -0,0 +1,8 @@ +use DB_NAME_dev; +db.dropDatabase(); +sleep(10000); +use DB_NAME_dev; +db.dropDatabase(); +sleep(10000); +use DB_NAME; +db.copyDatabase('DB_NAME', 'DB_NAME_dev'); diff --git a/.docker/config/prepare_prod.js b/.docker/config/prepare_prod.js new file mode 100644 index 000000000..c3246a470 --- /dev/null +++ b/.docker/config/prepare_prod.js @@ -0,0 +1,12 @@ +use DB_NAME; +db.dropDatabase(); +sleep(10000); +use DB_NAME; +db.dropDatabase(); +sleep(20000); +use DB_NAME; +db.dropDatabase(); +sleep(20000); +use DB_NAME_dev; +sleep(10000); +db.copyDatabase('DB_NAME_dev', 'DB_NAME'); diff --git a/.docker/config/update_variables.sh b/.docker/config/update_variables.sh new file mode 100644 index 000000000..de6fb7f80 --- /dev/null +++ b/.docker/config/update_variables.sh @@ -0,0 +1,2 @@ +sed -i "s|B2B_URI|$B2B_URI|g" /edidb/hbx_oracle/config/database.rb +sed -i "s|DB_NAME|$EDIDB_DB_NAME|g" /edidb/scripts/prepare* diff --git a/.docker/production/Dockerfile.gha b/.docker/production/Dockerfile.gha new file mode 100644 index 000000000..3ea2804f5 --- /dev/null +++ b/.docker/production/Dockerfile.gha @@ -0,0 +1,304 @@ +ARG COMMIT_SHA +ARG BRANCH=main +ARG GEM_OAUTH_TOKEN +ARG BUNDLE_GITHUB__COM=$GEM_OAUTH_TOKEN + +############################################ +### Base image ### +############################################ + +FROM ghcr.io/health-connector/gluedb:base as base +LABEL author="ideacrew" + +ENV USERNAME=gluedb + +ARG DEBIAN_FRONTEND=noninteractive +ARG BUNDLER_VERSION=1.17.3 + +# Must be set as ENV variable to overrride the default +ENV BUNDLER_VERSION=$BUNDLER_VERSION + +# Only add packages that aren't already in the base image +# https://github.com/docker-library/ruby/blob/99def14400fcd612782367830836dfcbc10c8c50/2.1/slim/Dockerfile +RUN apt-get update -qq \ + # && apt-get -yq dist-upgrade \ + && apt-get install -y \ + fontconfig \ + libffi6 \ + libxext6 \ + libxml2 \ + libxrender1 \ + libyaml-cpp0.5v5 \ + nano \ + openssl \ + p7zip-full \ + sshpass \ + unzip \ + vim \ + zip \ + zlibc \ + libjemalloc1 \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \ + && truncate -s 0 /var/log/*log + +# Configure bundler and PATH, install bundler version +ENV GEM_HOME=/usr/local/bundle +ENV BUNDLE_PATH=$GEM_HOME +ENV BUNDLE_APP_CONFIG=$BUNDLE_PATH +ENV BUNDLE_BIN=/usr/local/bin +ENV BUNDLE_JOBS=4 +ENV BUNDLE_RETRY=3 + +ENV LANG=C.UTF-8 + +ENV PATH=$HOME/bin:$BUNDLE_BIN:$GEM_HOME/gems/bin:$PATH + +RUN rm -f /usr/local/bin/ruby/gems/*/specifications/default/bundler-*.gemspec +RUN gem install bundler -v $BUNDLER_VERSION + +RUN groupadd --gid 1001 $USERNAME \ + && useradd --uid 1001 --gid $USERNAME --shell /bin/bash --create-home $USERNAME + +ENV HOME=/edidb +RUN mkdir $HOME \ + && chown -R $USERNAME:$USERNAME $HOME + +# Configure app home directory +WORKDIR $HOME + +ENV EDIDB_DEVISE_SECRET_KEY=4949641a374994854c0529feb329a81885867f044eb6c23102892e38bb32da437a94ee27eb4086b196f7273868d4b06c682948f5ced62385c548ba2d96898e20 + +# unused in Rails 3 +# ENV EDIDB_SECRET_KEY_BASE=c8d2b9b204fbac78081a88a2c29b28cfeb82e6ccd3664b3948b813463b5917b315dbbd3040e8dffcb5b68df427099db0ce03e59e2432dfe5d272923b00755b82 + +ENV RECEIVER_ID=000000001 + +ENV RAILS_ENV=production +ENV NODE_ENV=production + +############################################################################### +## Builder. Adds node and Yarn. Not necessary in production. ### +############################################################################## +FROM base as builder + +ARG DEBIAN_FRONTEND=noninteractive + +ARG NODE_MAJOR=12 +ENV NODE_MAJOR=$NODE_MAJOR + +RUN apt-get update -qq \ + && apt-get install -yq --no-install-recommends \ + build-essential \ + git \ + libxml2-dev \ + nodejs \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \ + && truncate -s 0 /var/log/*log + +######################################################## +# Node and Bundle for production +######################################################## +FROM builder as prod_gems_and_assets + +ARG GEM_OAUTH_TOKEN +ARG BUNDLE_GITHUB__COM=$GEM_OAUTH_TOKEN + +COPY --chown=$USERNAME:$USERNAME ./Gemfile $HOME/Gemfile +COPY --chown=$USERNAME:$USERNAME ./Gemfile.lock $HOME/Gemfile.lock + +RUN gem install libxml-ruby -v '2.9.0' --source 'https://rubygems.org/' + +ENV BUNDLE_WITHOUT=development:test +RUN bundle install + +COPY --chown=$USERNAME:$USERNAME . $HOME + +ARG HOSTNAME=localhost + +# Needed to run client swap script +ENV EDIDB_DB_HOST=${HOSTNAME} +ENV EDIDB_DB_PORT=27017 +ENV EDIDB_DB_NAME=edidb_prod +ENV RABBITMQ_URL=amqp://${HOSTNAME}:5672 + +COPY --chown=$USERNAME:$USERNAME ./config/exchange_prod.yml $HOME/config/exchange.yml + +RUN bundle exec rake assets:precompile + +# https://github.com/rubygems/rubygems/issues/3225 +RUN rm -rf $GEM_HOME/bundle/ruby/*/cache + +################################################################ +# Deployable image +################################################################ + +FROM base as deploy + +ARG HOSTNAME=localhost + +# Needed to run client swap script +ENV EDIDB_DB_AUTH=true +ENV EDIDB_DB_HOST=${HOSTNAME} +ENV EDIDB_DB_NAME=edidb_prod +ENV EDIDB_DB_PASSWORD=anything +ENV EDIDB_DB_PORT=27017 +ENV EDIDB_DB_REPLICA_SET_NAME=anything +ENV EDIDB_DB_USERNAME=anything +ENV RABBITMQ_URL=amqp://${HOSTNAME}:5672 + +# Copy prebuilt gems +COPY --chown=$USERNAME:$USERNAME --from=prod_gems_and_assets $BUNDLE_PATH $BUNDLE_PATH + +# Copy all app code again (sans gems, node_modules, assets) +COPY --chown=$USERNAME:$USERNAME . $HOME + +# Copy prebuilt assets +COPY --chown=$USERNAME:$USERNAME --from=prod_gems_and_assets $HOME/public $HOME/public + +# Copy environment-based config files +COPY --chown=$USERNAME:$USERNAME ./config/exchange_prod.yml $HOME/config/exchange.yml + +USER $USERNAME + +ENTRYPOINT ["bin/docker-entrypoint"] + +################################################################ +# Glue update image builder +################################################################ + +FROM builder as update_builder + +RUN apt-get update \ + && apt-get -yq dist-upgrade \ + && apt-get install -y \ + wget \ + default-jdk + +ARG GEM_OAUTH_TOKEN +ENV BUNDLE_GITHUB__COM=x-access-token:"$GEM_OAUTH_TOKEN" + +RUN git clone https://"$GEM_OAUTH_TOKEN"@github.com/ideacrew/ediparser.git +RUN git clone https://"$GEM_OAUTH_TOKEN"@github.com/health-connector/hbx_oracle.git + +RUN wget https://repo1.maven.org/maven2/org/jruby/jruby-dist/1.7.27/jruby-dist-1.7.27-bin.zip && unzip jruby-dist-1.7.27-bin.zip +ENV PATH=$HOME/jruby-1.7.27/bin:$PATH +WORKDIR $HOME/hbx_oracle +RUN unset BUNDLE_APP_CONFIG && \ + unset BUNDLE_BIN && \ + unset BUNDLE_PATH && \ + unset BUNDLER_VERSION && \ + unset GEM_HOME && \ + unset RUBYGEMS_VERSION && \ + jruby -S gem install bundler -v 1.17.1 && \ + jruby -S bundle install + + +################################################################ +# Glue update image builder +################################################################ + +FROM ghcr.io/health-connector/gluedb:${BRANCH}-${COMMIT_SHA} as update + +# Switch back to root to install system libraries +USER root + +RUN apt-get update && apt-get install wget gnupg software-properties-common dirmngr -y +# Install mongodb shell +RUN wget -qO - https://www.mongodb.org/static/pgp/server-4.2.asc | apt-key add - +RUN echo "deb http://repo.mongodb.org/apt/debian stretch/mongodb-org/4.2 main" | tee /etc/apt/sources.list.d/mongodb-org-4.2.list + +# Install required packages/libraries +RUN apt-get update \ + # && apt-get upgrade \ + # && apt-get -yq dist-upgrade \ + && apt-get install -y \ + curl \ + jq \ + mongodb-org-shell \ + default-jdk \ + xz-utils \ + gcc \ + build-essential \ + git \ + libgmp-dev \ + python \ + lftp + +RUN curl -fsSL https://deb.nodesource.com/setup_14.x | bash - +RUN apt-get install -y nodejs +RUN cd /root && curl -O https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-x86_64-deb8-linux.tar.xz && tar xf ghc-8.0.2-x86_64-deb8-linux.tar.xz && cd ghc-8.0.2 && ./configure && make install +RUN cd /root && git clone https://github.com/haskell/cabal.git && cd /root/cabal && git checkout Cabal-v1.24.2.0 && cd cabal-install && ./bootstrap.sh +ENV PATH=$PATH:$HOME/.cabal/bin +#ENV PATH=$HOME/jruby-1.7.27/bin:$PATH +RUN cabal update + +RUN echo '\ngem "rubycritic"' >> Gemfile +RUN bundle install --jobs 20 --retry 5 --without development test + +COPY --chown=$USERNAME:$USERNAME --from=update_builder $HOME/ediparser $HOME/ediparser +COPY --chown=$USERNAME:$USERNAME --from=update_builder $HOME/hbx_oracle $HOME/hbx_oracle +COPY --chown=$USERNAME:$USERNAME --from=update_builder $HOME/jruby-1.7.27 $HOME/jruby-1.7.27 + +RUN cd /edidb/ediparser && cabal update && cabal install --dependencies-only && cabal build && cabal configure +RUN mkdir -p /edidb/scripts + +COPY .docker/config/prepare_dev.js /edidb/scripts/prepare_dev.js +COPY .docker/config/prepare_prod.js /edidb/scripts/prepare_prod.js +COPY .docker/config/database.rb /edidb/hbx_oracle/config/database.rb +COPY .docker/config/update_variables.sh /edidb/scripts/update_variables.sh +RUN chmod 755 /edidb/scripts/update_variables.sh +COPY .docker/config/glue_update.sh /edidb/scripts/glue_update.sh +RUN chmod 755 /edidb/scripts/glue_update.sh + +RUN curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.20.14/bin/linux/amd64/kubectl +RUN chmod 744 ./kubectl +RUN mv ./kubectl /usr/local/bin/kubectl +RUN curl https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip -o "awscliv2.zip" && unzip awscliv2.zip && ./aws/install && rm awscliv2.zip +RUN npm install -g secure-spreadsheet +RUN chown -R $USERNAME:$USERNAME $HOME + +################################################################ +# Glue reports image builder +################################################################ + +FROM ghcr.io/health-connector/gluedb:${BRANCH}-${COMMIT_SHA} as reports + +# Switch back to root to install system libraries +USER root + +RUN apt-get update && apt-get install wget gnupg software-properties-common dirmngr -y +# Install mongodb shell +RUN wget -qO - https://www.mongodb.org/static/pgp/server-4.2.asc | apt-key add - +RUN echo "deb http://repo.mongodb.org/apt/debian stretch/mongodb-org/4.2 main" | tee /etc/apt/sources.list.d/mongodb-org-4.2.list + +# Install required packages/libraries +RUN apt-get update \ + # && apt-get upgrade \ + # && apt-get -yq dist-upgrade \ + && apt-get install -y \ + curl \ + jq \ + mongodb-org-shell \ + default-jdk \ + xz-utils \ + gcc \ + build-essential \ + git \ + libgmp-dev \ + python \ + lftp + +RUN curl -fsSL https://deb.nodesource.com/setup_14.x | bash - +RUN apt-get install -y nodejs + +RUN echo '\ngem "rubycritic"' >> Gemfile +RUN bundle install --jobs 20 --retry 5 --without development test + +RUN curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.20.14/bin/linux/amd64/kubectl +RUN chmod 744 ./kubectl +RUN mv ./kubectl /usr/local/bin/kubectl +RUN curl https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip -o "awscliv2.zip" && unzip awscliv2.zip && ./aws/install && rm awscliv2.zip +RUN npm install -g secure-spreadsheet +RUN chown -R $USERNAME:$USERNAME $HOME diff --git a/.github/workflows/build-and-deploy.yml b/.github/workflows/build-and-deploy.yml new file mode 100644 index 000000000..952446e33 --- /dev/null +++ b/.github/workflows/build-and-deploy.yml @@ -0,0 +1,186 @@ +name: Build Image and Deploy + +on: + workflow_dispatch: + push: + branches: + - "master" + pull_request: + branches: + - "master" + +concurrency: + group: docker-${{ github.ref }} + cancel-in-progress: true + +env: + RABBITMQ_DEFAULT_USER: "guest" + RABBITMQ_DEFAULT_PASS: "guest" + +jobs: + prep: + runs-on: ubuntu-latest + outputs: + taggedImage: ${{ steps.prep.outputs.tagged_image }} + tag: ${{ steps.prep.outputs.tag }} + registry_ghcr: ${{ steps.prep.outputs.registry_ghcr }} + shortSha: ${{ steps.prep.outputs.short_sha}} + branchName: ${{ steps.prep.outputs.branch_name }} + latestTag: ${{ steps.prep.outputs.latest_tag }} + repositoryName: ${{ steps.prep.outputs.repository_name }} + steps: + - name: Git branch name + id: git-branch-name + uses: EthanSK/git-branch-name-action@v1 + - name: Prepare info + id: prep + run: | + SHORT_SHA=$(echo $GITHUB_SHA | head -c7) + REPO=$(echo '${{ github.repository }}' | awk -F '/' '{print $2}') + TAG=${{ env.GIT_BRANCH_NAME }}-$(echo $GITHUB_SHA | head -c7) + IMAGE=health-connector/$REPO + echo "tagged_image=${IMAGE}:${TAG}" >> $GITHUB_OUTPUT + echo "tag=${TAG}" >> $GITHUB_OUTPUT + echo "registry_ghcr=ghcr.io" >> $GITHUB_OUTPUT + echo "short_sha=$SHORT_SHA" >> $GITHUB_OUTPUT + echo "branch_name=${{ env.GIT_BRANCH_NAME }}" >> $GITHUB_OUTPUT + echo "repository_name=$REPO" >> $GITHUB_OUTPUT + echo "latest_tag=${IMAGE}:latest" >> $GITHUB_OUTPUT + + # Uses buildx to build and push the image + build-and-upload-image: + needs: [prep] + runs-on: ubuntu-latest + services: + rabbitmq: + image: rabbitmq:latest + ports: + - 5672:5672 + - 15672:15672 + options: >- + --name "rabbitmq" + --health-cmd "rabbitmqctl node_health_check" + --health-interval 10s + --health-timeout 5s + --health-retries 5 + mongo: + image: mongo:4.2 + ports: + - 27017:27017 + options: >- + --name "mongo" + --health-cmd mongo + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: + - uses: actions/checkout@v3 + + - name: Add git HEAD info to docker image + run: git show --quiet HEAD > release.txt + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + with: + install: true + version: v0.9.1 + + - name: Cache Docker layers + uses: actions/cache@v3 + with: + path: /tmp/.buildx-cache + # Key is named differently to avoid collision + key: ${{ runner.os }}-multi-buildx-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-multi-buildx + + # Add vhosts to RabbitMQ + - run: | + docker exec rabbitmq rabbitmqctl add_vhost / + docker exec rabbitmq rabbitmqctl add_vhost event_source + docker exec rabbitmq rabbitmqctl set_permissions -p event_source guest ".*" ".*" ".*" + + - name: Login to GHCR + uses: docker/login-action@v2 + with: + registry: ${{ needs.prep.outputs.registry_ghcr }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build Image + uses: docker/build-push-action@v3 + with: + context: . + builder: ${{ steps.buildx.outputs.name }} + file: .docker/production/Dockerfile.gha + # Set the desired build target here + target: deploy + # needed to access mongo and rabbit on GHA machine + network: host + # send to public registry if not a pull request + push: ${{ github.event_name != 'pull_request' }} + # create local image (for scanning) if it is a pull request + load: ${{ github.event_name == 'pull_request' }} + tags: | + ${{ format('{0}/{1}', needs.prep.outputs.registry_ghcr, needs.prep.outputs.taggedImage) }} + ${{ format('{0}/{1}', needs.prep.outputs.registry_ghcr, needs.prep.outputs.latestTag) }} + cache-from: type=local,src=/tmp/.buildx-cache + # Note the mode=max here + # More: https://github.com/moby/buildkit#--export-cache-options + # And: https://github.com/docker/buildx#--cache-tonametypetypekeyvalue + cache-to: type=local,mode=max,dest=/tmp/.buildx-cache-new + build-args: | + HOSTNAME=172.17.0.1 + GEM_OAUTH_TOKEN=${{ secrets.dchbx_deployments_token }} + + - name: Scan Docker image + if: github.event_name != 'pull_request' + id: scan + uses: anchore/scan-action@main + with: + image: ${{ format('{0}/{1}', needs.prep.outputs.registry_ghcr, needs.prep.outputs.taggedImage) }} + # acs-report-enable: true + fail-build: false + severity-cutoff: critical + + # - name: upload Anchore scan SARIF report + # if: github.event_name != 'pull_request' + # uses: github/codeql-action/upload-sarif@v1 + # with: + # sarif_file: ${{ steps.scan.outputs.sarif }} + + - name: Move cache + run: | + rm -rf /tmp/.buildx-cache + mv /tmp/.buildx-cache-new /tmp/.buildx-cache + + # notify-slack: + # if: github.event_name != 'pull_request' + # needs: [prep, build-and-upload-image] + # runs-on: ubuntu-latest + # strategy: + # matrix: + # registry: ['ghcr.io'] + # steps: + # - name: Post to a Slack channel + # id: slack + # uses: slackapi/slack-github-action@v1.16.0 + # with: + # channel-id: "docker-images-${{ needs.prep.outputs.repositoryName }}" + # payload: | + # { + # "blocks": [ + # { + # "type": "section", + # "text": { + # "type": "mrkdwn", + # "text": "*${{ format('{0} image*:\n`{1}/{2}`', matrix.registry, matrix.registry, needs.prep.outputs.taggedImage) }}" + # } + # }, + # { + # "type": "divider" + # } + # ] + # } + # env: + # SLACK_BOT_TOKEN: ${{ secrets.CCA_DEPLOY_SLACK_BOT_TOKEN }} diff --git a/.github/workflows/build-base-image.yml b/.github/workflows/build-base-image.yml new file mode 100644 index 000000000..fc30b890b --- /dev/null +++ b/.github/workflows/build-base-image.yml @@ -0,0 +1,60 @@ +name: Build Base Image + +on: + workflow_dispatch: + push: + branches: + - "main" + paths: + - ".docker/base/**" + +concurrency: + group: base-${{ github.ref }} + cancel-in-progress: true + +jobs: + # Uses buildx to build and push the image + build-and-upload-image: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + with: + install: true + + - name: Cache Docker layers + uses: actions/cache@v3 + with: + path: /tmp/.buildx-cache + # Key is named differently to avoid collision + key: ${{ runner.os }}-multi-buildx-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-multi-buildx + + - name: Login to GHCR + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build Image + uses: docker/build-push-action@v3 + with: + context: . + builder: ${{ steps.buildx.outputs.name }} + file: .docker/base/Dockerfile.base + push: "true" + tags: ghcr.io/health-connector/gluedb:base + cache-from: type=local,src=/tmp/.buildx-cache + # Note the mode=max here + # More: https://github.com/moby/buildkit#--export-cache-options + # And: https://github.com/docker/buildx#--cache-tonametypetypekeyvalue + cache-to: type=local,mode=max,dest=/tmp/.buildx-cache-new + + - name: Move cache + run: | + rm -rf /tmp/.buildx-cache + mv /tmp/.buildx-cache-new /tmp/.buildx-cache diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..b4aeaf74c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,28 @@ +FROM --platform=linux/amd64 debian:stretch +RUN echo "deb http://archive.debian.org/debian stretch main" > /etc/apt/sources.list +RUN echo "deb http://archive.debian.org/debian-security stretch/updates main" >> /etc/apt/sources.list + +RUN apt-get update && \ + apt-get install -y git gcc openssl libyaml-dev libyaml-cpp-dev curl libffi-dev libreadline-dev \ + zlibc libgdbm-dev libncurses-dev autoconf fontconfig unzip zip sshpass bzip2 libxrender1 libxext6 \ + build-essential libxml2 libxml2-dev libxslt1-dev libz-dev libssl1.0-dev python + +WORKDIR /usr/src/ +RUN curl -O https://cache.ruby-lang.org/pub/ruby/2.1/ruby-2.1.10.tar.bz2 +RUN tar xjf ruby-2.1.10.tar.bz2 +RUN cd ruby-2.1.10 && ./configure && make -j 2 +RUN cd ruby-2.1.10 && make install + +WORKDIR /usr/src/app +# Adding gems +COPY Gemfile Gemfile +COPY Gemfile.lock Gemfile.lock + +RUN gem install bundler --version "1.17.3" + +# Setting env up +ARG GEM_OAUTH_TOKEN +ENV BUNDLE_GITHUB__COM=x-access-token:"$GEM_OAUTH_TOKEN" + +RUN bundle install --jobs 20 --retry 5 + diff --git a/Gemfile b/Gemfile index 8809b010e..37797267d 100644 --- a/Gemfile +++ b/Gemfile @@ -99,3 +99,4 @@ gem 'aws-sdk' # configuration support gem "config", '1.0.0' +gem "puma", "~>2.16" \ No newline at end of file diff --git a/Gemfile.lock b/Gemfile.lock index c46b6cdfc..fdc983787 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -288,6 +288,7 @@ GEM pdf-reader (>= 0.9.0) ttfunk (~> 1.0.0) psych (2.0.5) + puma (2.16.0) rack (1.4.7) rack-cache (1.7.1) rack (>= 0.4) @@ -492,6 +493,7 @@ DEPENDENCIES pd_x12 prawn (~> 0.11.1) psych (= 2.0.5) + puma (~> 2.16) rails (= 3.2.22.5) rails_best_practices rake (= 10.4.2) diff --git a/app/models/exchange_information.rb b/app/models/exchange_information.rb index 49274c923..f9d7c7b60 100644 --- a/app/models/exchange_information.rb +++ b/app/models/exchange_information.rb @@ -26,7 +26,7 @@ def initialize(key) # TODO: I have a feeling we may be using this pattern # A LOT. Look into extracting it if we repeat. def initialize - @config = YAML.load_file(File.join(Rails.root,'config', 'exchange.yml')) + @config = YAML.load(ERB.new(File.read(File.join(Rails.root,'config', 'exchange.yml'))).result) ensure_configuration_values(@config) end diff --git a/bin/docker-entrypoint b/bin/docker-entrypoint new file mode 100755 index 000000000..21a60b9fc --- /dev/null +++ b/bin/docker-entrypoint @@ -0,0 +1,9 @@ +#!/bin/bash -e + +# Enable jemalloc for reduced memory usage and latency, especially in production +if [ -z "${LD_PRELOAD+x}" ]; then + LD_PRELOAD=$(find /usr/lib -name libjemalloc.so.1 -print -quit) + export LD_PRELOAD +fi + +exec "${@}" \ No newline at end of file diff --git a/config/environments/production.rb b/config/environments/production.rb index 1a6edba1c..01b238541 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -9,7 +9,7 @@ config.action_controller.perform_caching = true # Disable Rails's static asset server (Apache or nginx will already do this) - config.serve_static_assets = false + config.serve_static_assets = true # Compress JavaScripts and CSS config.assets.compress = false @@ -52,7 +52,7 @@ # Disable delivery errors, bad email addresses will be ignored # config.action_mailer.raise_delivery_errors = false - config.action_mailer.default_url_options = { :host => "10.83.85.127" } + config.action_mailer.default_url_options = { :host => "#{ENV['EDIDB_FQDN']}" } # Enable threaded mode # config.threadsafe! diff --git a/config/exchange_prod.yml b/config/exchange_prod.yml new file mode 100644 index 000000000..85d439bbd --- /dev/null +++ b/config/exchange_prod.yml @@ -0,0 +1,12 @@ +# this file is used to configure the exchange for Rails "production" mode +# There, the file will be renamed to config/exchange.yml +receiver_id: "<%= ENV['RECEIVER_ID'] || '000000001' %>" +environment: "<%= ENV['ENV_NAME'] || 'dev' %>" +hbx_id: "<%= ENV['HBX_ID'] || 'hx0' %>" +invalid_argument_queue: "<%= ENV['HBX_ID'] || 'hx0' %>.errors.invalid_arguements" +processing_failure_queue: "<%= ENV['HBX_ID'] || 'hx0' %>.errors.processing_failures" +event_exchange: "<%= ENV['HBX_ID'] || 'hx0' %>.<%= ENV['ENV_NAME'] || 'dev' %>.e.topic.events" +event_publish_exchange: "<%= ENV['HBX_ID'] || 'hx0' %>.<%= ENV['ENV_NAME'] || 'dev' %>.e.fanout.events" +request_exchange: "<%= ENV['HBX_ID'] || 'hx0'%>.<%= ENV['ENV_NAME'] || 'dev' %>.e.direct.requests" +amqp_uri: "amqp://<%= ENV['RABBMITMQ_USER'] || 'guest' %>.<%= ENV['RABBITMQ_PASSWORD'] || 'guest' %>@<%= ENV['ACAPI_BROKER_HOST'] || 'localhost' %>:<%= ENV['ACAPI_BROKER_PORT'] || '5672' %>" +file_storage_uri: "<%= ENV['DOCUMENTS_URL'] || 'localhost' %>" diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index c94f07baf..b7d999a35 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -4,13 +4,20 @@ # The secret key used by Devise. Devise uses this key to generate # random tokens. Changing this key will render invalid all existing # confirmation, reset password and unlock tokens in the database. - config.secret_key = 'df6314776636c88eec8adde3294dfe0877265bdee010dea4ae13325eaa82fea0cc19e858fa469187554f42b8c19697de0603bd07529afff8acaf9cdf99779a09' + # BRH note: In rails 3, there is no rails secret_key_base to fall back to for non-prod envs, so this always requires a value. + # https://github.com/heartcombo/devise/blob/v3.3.0/lib/generators/templates/devise.rb. In local dev envs, uses a default + # value. + config.secret_key = if Rails.env.production? + ENV['EDIDB_DEVISE_SECRET_KEY'] + else + 'df6314776636c88eec8adde3294dfe0877265bdee010dea4ae13325eaa82fea0cc19e858fa469187554f42b8c19697de0603bd07529afff8acaf9cdf99779a09' + end # ==> Mailer Configuration # Configure the e-mail address which will be shown in Devise::Mailer, # note that it will be overwritten if you use your own mailer class # with default "from" parameter. - config.mailer_sender = 'please-change-me-at-config-initializers-devise@example.com' + config.mailer_sender = Rails.env.production? ? ENV['EDIDB_DEVISE_MAILER_SENDER'] : 'please-change-me-at-config-initializers-devise@example.com' # Configure the class responsible to send e-mails. # config.mailer = 'Devise::Mailer' @@ -126,6 +133,9 @@ # The time the user will be remembered without asking for credentials again. # config.remember_for = 2.weeks + # Invalidates all the remember me tokens when the user signs out. + config.expire_all_remember_me_on_sign_out = true + # If true, extends the user's remember period when remembered via cookie. # config.extend_remember_period = false @@ -135,7 +145,7 @@ # ==> Configuration for :validatable # Range for password length. Default is 8..128. - config.password_length = 8..128 + config.password_length = 8..20 # Email regex used to validate email formats. It simply asserts that # one (and only one) @ exists in the given string. This is mainly @@ -145,7 +155,7 @@ # ==> Configuration for :timeoutable # The time you want to timeout the user session without activity. After this # time the user will be asked for credentials again. Default is 30 minutes. - # config.timeout_in = 30.minutes + config.timeout_in = Rails.env.production? ? 15.minutes : 30.minutes # If true, expires auth token on session timeout. # config.expire_auth_token_on_timeout = false @@ -154,7 +164,7 @@ # Defines which strategy will be used to lock an account. # :failed_attempts = Locks an account after a number of failed attempts to sign in. # :none = No lock strategy. You should handle locking by yourself. - # config.lock_strategy = :failed_attempts + config.lock_strategy = :failed_attempts # Defines which key will be used when locking and unlocking an account # config.unlock_keys = [ :email ] @@ -164,17 +174,17 @@ # :time = Re-enables login after a certain amount of time (see :unlock_in below) # :both = Enables both strategies # :none = No unlock strategy. You should handle unlocking by yourself. - # config.unlock_strategy = :both + config.unlock_strategy = :both # Number of authentication tries before locking an account if lock_strategy # is failed attempts. - # config.maximum_attempts = 20 + config.maximum_attempts = Rails.env.production? ? 7 : 20 # Time interval to unlock the account if :time is enabled as unlock_strategy. # config.unlock_in = 1.hour # Warn on the last attempt before the account is locked. - # config.last_attempt_warning = false + config.last_attempt_warning = true # ==> Configuration for :recoverable # @@ -222,7 +232,7 @@ # config.navigational_formats = ['*/*', :html] # The default HTTP method used to sign out a resource. Default is :delete. - config.sign_out_via = :delete + config.sign_out_via = [:delete,:get] # ==> OmniAuth # Add a new OmniAuth provider. Check the wiki for more information on setting diff --git a/config/mongoid.yml b/config/mongoid.yml index 6da7e0f34..71af75784 100644 --- a/config/mongoid.yml +++ b/config/mongoid.yml @@ -1,3 +1,27 @@ +production: + sessions: + default: + # Defines the name of the default database that Mongoid can connect to. + # (required). + database: <%= ENV['EDIDB_DB_NAME'] || 'edidb_prod' %> + <% if ENV['EDIDB_DB_AUTH'] %> + username: <%= ENV['EDIDB_DB_USERNAME'] %> + password: <%= ENV['EDIDB_DB_PASSWORD'] %> + <% end %> + + hosts: + - <%= ENV['EDIDB_DB_HOST'] || 'localhost' %>:<%= ENV['EDIDB_DB_PORT'] || '27017' %> + options: + <% if ENV['EDIDB_DB_AUTH'] %> + replica_set: <%= ENV['EDIDB_DB_REPLICA_SET_NAME'] %> + <% end %> + + write: + w: 1 + j: true + + skip_version_check: true + development: # Configure available database sessions. (required) sessions: diff --git a/config/puma.rb b/config/puma.rb new file mode 100644 index 000000000..8e9e10ee1 --- /dev/null +++ b/config/puma.rb @@ -0,0 +1,18 @@ +environment ENV.fetch("RAILS_ENV", "development") +bind "tcp://0.0.0.0:#{ENV['PORT'] || 3000}" +pidfile "/edidb/tmp/pids/puma.pid" +#threads 1,1 +max_threads_count = ENV.fetch("RAILS_MAX_THREADS", 5) +min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count } +threads min_threads_count, max_threads_count + +on_worker_boot do + Mongoid::Clients.clients.each_value do |client| + client.close + client.reconnect + end +end + +before_fork do + Mongoid.disconnect_clients +end diff --git a/log/.gitkeep b/log/.gitkeep new file mode 100644 index 000000000..e69de29bb