Skip to content

Controlplane setup #507

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Jan 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions .controlplane/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
FROM ruby:3.1.2

RUN apt-get update

# install node and yarn
RUN curl -sL https://deb.nodesource.com/setup_16.x | bash
RUN apt-get install -y nodejs
RUN npm install -g yarn

WORKDIR /app

# install ruby gems
COPY Gemfile* ./

RUN bundle config set without 'development test' && \
bundle config set with 'staging production' && \
bundle install --jobs=3 --retry=3

# install node packages
COPY package.json yarn.lock .
RUN yarn install

# pick necessary app files
COPY Gemfile* config.ru Rakefile babel.config.js ./
COPY app ./app
COPY bin ./bin
COPY client ./client
COPY config ./config
COPY db ./db
COPY lib ./lib
COPY public ./public

ENV RAILS_ENV=production
ENV NODE_ENV=production

ENV SECRET_KEY_BASE=NOT_USED_NON_BLANK

# compiling assets requires any value for ENV of SECRET_KEY_BASE
RUN rails react_on_rails:locale && rails assets:precompile

# add entrypoint
COPY .controlplane/entrypoint.sh ./
ENTRYPOINT ["/app/entrypoint.sh"]

CMD ["rails", "s"]
25 changes: 25 additions & 0 deletions .controlplane/controlplane.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Configuration for "Heroku to CPLN playbook" custom scripts
aliases:
common: &common
# Change this to your org name for staging. Production apps will use a different org
# for security.
org: your-org-name-for-staging
# Example apps use only location. CPLN offers the ability to use multiple locations.
location: aws-us-east-2
# Configure the workload name used as a template for one-off scripts, like a Heroku one-off dyno.
one_off_workload: rails
# Like the entries in the Heroku Procfile that get deployed when the application code changes
# and the application image updates.
app_workloads:
- rails
# Like Heroku add-ons
additional_workloads:
- redis
- postgres
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dzirtusss why do we nee to list these?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

those are used in ps command atm - ps, ps:start, ps:stop, ps:restart. however, there is no clear plan about their future need atm


apps:
ror-tutorial:
<<: *common
ror-tutorial-review:
<<: *common
prefix: true
25 changes: 25 additions & 0 deletions .controlplane/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/bin/sh
# Runs before the main command

wait_for_service()
{
until curl -I -sS $1 2>&1 | grep -q "Empty reply from server"; do
echo " -- $1 is unavailable, sleeping..."
sleep 1
done
echo " -- $1 is available"
}

echo " -- Starting entrypoint.sh"

echo " -- Waiting for services"

# Strip out the host and the port for curl and to keep full resource URL secret
wait_for_service $(echo $DATABASE_URL | sed -e 's|^.*@||' -e 's|/.*$||')
wait_for_service $(echo $REDIS_URL | sed -e 's|redis://||' -e 's|/.*$||')

echo " -- Preparing database"
rails db:prepare

echo " -- Finishing entrypoint.sh, executing '$@'"
exec "$@"
58 changes: 58 additions & 0 deletions .controlplane/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Deploying tutorial app on Control Plane

## Prerequisites

1. Should have [Control Plane](https://controlplane.com) account set up.

2. Set up `organization` for testing in that account and modify org `.controlplane/controlplane.yml` .

3. Install Control Plane CLI (and configure access) [docs here](https://docs.controlplane.com/quickstart/quick-start-3-cli#getting-started-with-the-cli).

4. Install Heroku to Control Plane playbook from https://github.com/shakacode/heroku-to-control-plane.

## Setup and run

Check if the organization and location are correct in `.controlplane/controlplane.yml`.

```sh
# Note, below commands use `cpl` which is the Heroku to Control Plane playbook script.

# Provision all infrastructure on Control Plane. It will use templates from .controlplane/templates folder.
cpl setup gvc postgres redis rails -a ror-tutorial

# Build and push docker image to Control Plane repository
cpl build -a ror-tutorial

# Promote image to app after running `cpl build command`
cpl promote -a ror-tutorial

# See how app is starting up
cpl logs -a ror-tutorial

# Open app in browser (once it has started up)
cpl open -a ror-tutorial
```

## Promoting code upgrades

```sh
# Build and push new image with sequential image tagging, e.g. 'ror-tutorial_123'
cpl build -a ror-tutorial

# OR
# Build and push with sequential image tagging and commit SHA, e.g. 'ror-tutorial_123_ABCD'
cpl build -a ror-tutorial --commit ABCD

# Run database migrations (or other release tasks) with latest image,
# while app is still running on previous image
cpl runner rails db:migrate -a ror-tutorial --image latest

# Pomote latest image to app
promote -a ror-tutorial
```

## Other notes

### `entrypoint.sh`
- waits for Postgres and Redis to be available
- runs `rails db:prepare` to create/seed or migrate the database
25 changes: 25 additions & 0 deletions .controlplane/templates/gvc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Template setup of the GVC, roughly corresponding to a Heroku app
kind: gvc
name: APP_GVC
spec:
# For using templates for test apps, put ENV values here, stored in git repo.
# Production apps will have values configured manually after app creation.
env:
- name: DATABASE_URL
# Password does not matter because host postgres.APP_GVC.cpln.local can only be accessed
# locally within CPLN GVC, and postgres running on a CPLN workload is something only for a
# test app that lacks persistence.
value: 'postgres://postgres:password123@postgres.APP_GVC.cpln.local:5432/APP_GVC'
- name: RAILS_ENV
value: production
- name: NODE_ENV
value: production
- name: RAILS_SERVE_STATIC_FILES
value: 'true'
- name: REDIS_URL
# No password for GVC local Redis. See comment above for postgres.
value: 'redis://redis.APP_GVC.cpln.local:6379'
# Part of standard configuration
staticPlacement:
locationLinks:
- /org/APP_ORG/location/APP_LOCATION
33 changes: 33 additions & 0 deletions .controlplane/templates/postgres.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Template setup of Postgres workload, roughly corresponding to a Heroku add-on for a database
kind: workload
name: postgres
spec:
type: standard
containers:
- name: postgres
env:
- name: PGUSER
value: postgres
# Hardcoded password. See firewall comment below.
- name: POSTGRES_PASSWORD
value: password123
- name: POSTGRES_USER
value: postgres
image: 'postgres:13.8-alpine'
ports:
- number: 5432
protocol: tcp
volumes:
- path: /var/lib/postgresql/data
recoveryPolicy: retain
uri: 'scratch://postgres-vol'
# Important that postgres does not scaling because disk storage is local to one server!
defaultOptions:
autoscaling:
maxScale: 1
capacityAI: false
# This firewall configuration corresponds to using a simple, hard-coded password for postgres
# in the gvc.yml template.
firewallConfig:
internal:
inboundAllowType: same-gvc
36 changes: 36 additions & 0 deletions .controlplane/templates/rails.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Template setup of Rails server workload, roughly corresponding to Heroku dyno
# type within Procfile.
kind: workload
name: rails
spec:
type: standard
containers:
- name: rails
# 300m is a good starting place for a test app. You can experiment with CPU configuration
# once your app is running.
cpu: 300m
env:
- name: LOG_LEVEL
value: debug
# Inherit other ENV values from GVC
inheritEnv: true
image: '/org/APP_ORG/image/APP_IMAGE'
# 512 corresponds to a standard 1x dyno type
memory: 512Mi
ports:
- number: 3000
protocol: http
defaultOptions:
# Start out like this for "test apps"
autoscaling:
# Max of 1 effectively disables autoscaling, so a like a Heroku dyno count of 1
maxScale: 1
capacityAI: false
firewallConfig:
external:
# Default to allow public access to Rails server
inboundAllowCIDR:
- 0.0.0.0/0
# Could configure outbound for more security
outboundAllowCIDR:
- 0.0.0.0/0
18 changes: 18 additions & 0 deletions .controlplane/templates/redis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
kind: workload
name: redis
spec:
type: standard
containers:
- name: redis
image: 'redis:6.2.6'
ports:
- number: 6379
protocol: tcp
defaultOptions:
autoscaling:
maxScale: 1
capacityAI: false
# This firewall configuration corresponds to using no password for Redis in the gvc.yml template.
firewallConfig:
internal:
inboundAllowType: same-gvc
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
node_modules
npm-debug.log*
/coverage
dump.rdb
.DS_Store

# Ignore bundle dependencies
vendor/ruby
Expand Down
11 changes: 7 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
# TODO: Document where used
# Maybe outdated.
# Control Plane setup is in the .controlplane directory
FROM ruby:3.1.2

RUN apt-get update

RUN curl -sL https://deb.nodesource.com/setup_16.x | bash
RUN apt-get install -y nodejs
RUN apt-get install -y nodejs
RUN npm install -g yarn

WORKDIR /app
COPY Gemfile* ./

RUN bundle install

COPY package.json .
COPY package.json yarn.lock .
RUN yarn install

COPY . .

RUN rake react_on_rails:locale && RAILS_ENV=production rake assets:precompile
RUN rails react_on_rails:locale && RAILS_ENV=production rails assets:precompile
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice to set NODE_ENV=production as well.


ENV RAILS_ENV=production
ENV RAILS_ENV=production
ENV NODE_ENV=production
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move these lines above the precompile.


CMD ["rails", "s"]
4 changes: 4 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ gem "autoprefixer-rails"

gem "awesome_print"

# FIXME: quick fix for rails6, not needed since rails 7.0.1
# https://github.com/rails/rails/pull/44083
gem "net-imap", require: false
gem "net-pop", require: false
gem "net-smtp", require: false

# jquery as the JavaScript library has been moved under /client and managed by npm.
Expand Down
8 changes: 8 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ GEM
activerecord (>= 5.a)
database_cleaner-core (~> 2.0.0)
database_cleaner-core (2.0.1)
date (3.3.2)
debug_inspector (1.1.0)
diff-lcs (1.5.0)
docile (1.4.0)
Expand Down Expand Up @@ -149,6 +150,11 @@ GEM
mini_mime (1.1.2)
mini_portile2 (2.6.1)
minitest (5.15.0)
net-imap (0.3.2)
date
net-protocol
net-pop (0.1.2)
net-protocol
net-protocol (0.1.3)
timeout
net-smtp (0.3.2)
Expand Down Expand Up @@ -370,6 +376,8 @@ DEPENDENCIES
jbuilder
launchy
listen
net-imap
net-pop
net-smtp
pg
pry
Expand Down
6 changes: 0 additions & 6 deletions config/secrets.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,11 @@

development:
secret_key_base: 231bf79489c63f8c8facd7bf27db1c2582a42a7f4302fccdb74ef35bc5dc91fb4e19dbf167f3003bdb4073818dfab4a9916890d193d535a7be458dbef1609800
action_cable_url : http://localhost:3000

test:
secret_key_base: 1ab8adbcf8410aebbce9b6dd6db7b5d090297bd22cf789b91ff44ae02711e8c128453d3e5c97eadf9066efe1a1e0dc1921faf7314d566c114d3ed60ae7ea614c
action_cable_url : http://localhost:3000

# Do not keep production secrets in the repository,
# instead read values from the environment.
production:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
action_cable_url : <%= ENV["SERVER_PORT"] %>
# Real life, set the ENV value
# secret_key_base: <%#= ENV["SECRET_KEY_BASE"] %>
# action_cable_url : <%= ENV["SERVER_PORT"] %>