├── .github └── workflows │ └── openshift-tests.yml ├── .gitignore ├── .s2i └── bin │ └── assemble ├── Gemfile ├── Gemfile.lock ├── Makefile ├── README.md ├── Rakefile ├── app ├── assets │ ├── config │ │ └── manifest.js │ ├── images │ │ └── .keep │ ├── javascripts │ │ ├── application.js │ │ ├── articles.coffee │ │ ├── cable.js │ │ ├── channels │ │ │ └── .keep │ │ ├── comments.coffee │ │ └── welcome.coffee │ └── stylesheets │ │ ├── application.css │ │ ├── articles.scss │ │ ├── comments.scss │ │ ├── scaffolds.scss │ │ └── welcome.scss ├── channels │ └── application_cable │ │ ├── channel.rb │ │ └── connection.rb ├── controllers │ ├── application_controller.rb │ ├── articles_controller.rb │ ├── comments_controller.rb │ ├── concerns │ │ └── .keep │ └── welcome_controller.rb ├── helpers │ ├── application_helper.rb │ ├── articles_helper.rb │ ├── comments_helper.rb │ └── welcome_helper.rb ├── jobs │ └── application_job.rb ├── mailers │ └── application_mailer.rb ├── models │ ├── application_record.rb │ ├── article.rb │ ├── comment.rb │ └── concerns │ │ └── .keep └── views │ ├── articles │ ├── _article.json.jbuilder │ ├── _form.html.erb │ ├── edit.html.erb │ ├── index.html.erb │ ├── index.json.jbuilder │ ├── new.html.erb │ ├── show.html.erb │ └── show.json.jbuilder │ ├── layouts │ ├── application.html.erb │ ├── mailer.html.erb │ └── mailer.text.erb │ └── welcome │ └── index.html.erb ├── bin ├── rails ├── rake ├── setup ├── spring └── update ├── config.ru ├── config ├── application.rb ├── boot.rb ├── cable.yml ├── database.yml ├── environment.rb ├── environments │ ├── development.rb │ ├── production.rb │ └── test.rb ├── initializers │ ├── application_controller_renderer.rb │ ├── assets.rb │ ├── backtrace_silencers.rb │ ├── content_security_policy.rb │ ├── cookies_serializer.rb │ ├── filter_parameter_logging.rb │ ├── inflections.rb │ ├── mime_types.rb │ ├── new_framework_defaults.rb │ ├── new_framework_defaults_6_1.rb │ ├── permissions_policy.rb │ ├── session_store.rb │ └── wrap_parameters.rb ├── locales │ └── en.yml ├── puma.rb ├── routes.rb ├── secrets.yml ├── spring.rb └── storage.yml ├── db ├── migrate │ ├── 20161103112943_create_articles.rb │ └── 20161103113002_create_comments.rb ├── schema.rb └── seeds.rb ├── lib ├── assets │ └── .keep └── tasks │ └── .keep ├── migrate-database.sh ├── openshift └── templates │ ├── rails-postgresql-persistent.json │ ├── rails-postgresql.json │ └── rails.json ├── public ├── 404.html ├── 422.html ├── 500.html ├── apple-touch-icon-precomposed.png ├── apple-touch-icon.png ├── favicon.ico ├── index.html └── robots.txt ├── test ├── application_system_test_case.rb ├── controllers │ ├── .keep │ ├── articles_controller_test.rb │ ├── comments_controller_test.rb │ └── welcome_controller_test.rb ├── fixtures │ ├── .keep │ ├── articles.yml │ ├── comments.yml │ └── files │ │ └── .keep ├── helpers │ └── .keep ├── integration │ └── .keep ├── mailers │ └── .keep ├── models │ ├── .keep │ ├── article_test.rb │ └── comment_test.rb ├── system │ └── .keep └── test_helper.rb ├── tests ├── test_rails.py └── test_rails_postgresql.py └── vendor ├── .keep └── assets ├── javascripts └── .keep └── stylesheets └── .keep /.github/workflows/openshift-tests.yml: -------------------------------------------------------------------------------- 1 | on: 2 | issue_comment: 3 | types: 4 | - created 5 | jobs: 6 | openshift-tests: 7 | # This job only runs for '[test] pull request comments by owner, member 8 | name: "RHEL9 tests: imagestream ${{ matrix.version }}" 9 | runs-on: ubuntu-latest 10 | strategy: 11 | fail-fast: false 12 | matrix: 13 | version: [ "2.5-ubi8", "3.0-ubi9", "3.3-ubi8", "3.3-ubi9" ] 14 | 15 | if: | 16 | github.event.issue.pull_request 17 | && contains(github.event.comment.body, '[test]') 18 | && contains(fromJson('["OWNER", "MEMBER"]'), github.event.comment.author_association) 19 | steps: 20 | - uses: sclorg/testing-farm-as-github-action@main 21 | with: 22 | api_key: ${{ secrets.TF_INTERNAL_API_KEY }} 23 | compose: "RHEL-9.4.0-Nightly" 24 | git_url: "https://gitlab.cee.redhat.com/platform-eng-core-services/sclorg-tmt-plans" 25 | git_ref: "master" 26 | tf_scope: "private" 27 | tmt_plan_regex: "rhel9-openshift-pytest" 28 | update_pull_request_status: true 29 | pull_request_status_name: "RHEL9-OpenShift-4 - imagestream test ${{ matrix.version }}" 30 | variables: "REPO_URL=${{ github.server_url }}/${{ github.repository }};REPO_NAME=${{ github.repository }};PR_NUMBER=${{ github.event.issue.number }};OS=rhel9;SINGLE_VERSION=${{ matrix.version }};TEST_NAME=test-openshift-pytest" 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files for more about ignoring files. 2 | # 3 | # If you find yourself ignoring temporary files generated by your text editor 4 | # or operating system, you probably want to add a global ignore instead: 5 | # git config --global core.excludesfile '~/.gitignore_global' 6 | 7 | # Ignore bundler config. 8 | /.bundle 9 | 10 | # Ignore the default SQLite database. 11 | /db/*.sqlite3 12 | /db/*.sqlite3-journal 13 | 14 | # Ignore all logfiles and tempfiles. 15 | /log/* 16 | /tmp/* 17 | !/log/.keep 18 | !/tmp/.keep 19 | log/ 20 | tmp/ 21 | 22 | # Ignore Byebug command history file. 23 | .byebug_history 24 | /config/master.key 25 | -------------------------------------------------------------------------------- /.s2i/bin/assemble: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ASSEMBLE_SCRIPT="/usr/libexec/s2i/assemble" 4 | 5 | pushd /tmp/src || exit 1 6 | 7 | echo "---> Building your Ruby application from source ..." 8 | if [ -f Gemfile ]; then 9 | ADDTL_BUNDLE_ARGS="--retry 2" 10 | if [ -f Gemfile.lock ]; then 11 | # This is new in version 3.0 12 | # [DEPRECATED] The `--deployment` flag is deprecated because it relies 13 | # on being remembered across bundler invocations, 14 | # which bundler will no longer do in future versions. 15 | # Instead please use `bundle config set --local deployment 'true'`, 16 | # and stop using this flag 17 | bundle config --local deployment 'true' 18 | fi 19 | 20 | if [[ "$RAILS_ENV" == "development" || "$RACK_ENV" == "development" ]]; then 21 | BUNDLE_WITHOUT=${BUNDLE_WITHOUT:-"test"} 22 | elif [[ "$RAILS_ENV" == "test" || "$RACK_ENV" == "test" ]]; then 23 | BUNDLE_WITHOUT=${BUNDLE_WITHOUT:-"development"} 24 | else 25 | BUNDLE_WITHOUT=${BUNDLE_WITHOUT:-"development:test"} 26 | fi 27 | 28 | if [ -n "$BUNDLE_WITHOUT" ]; then 29 | # [DEPRECATED] The `--without` flag is deprecated because 30 | # it relies on being remembered across bundler invocations, 31 | # which bundler will no longer do in future versions. 32 | # Instead please use `bundle config set --local without ''test''`, 33 | # and stop using this flag 34 | bundle config --local without "$BUNDLE_WITHOUT" 35 | fi 36 | 37 | echo "---> Running 'bundle install ${ADDTL_BUNDLE_ARGS}' ..." 38 | # [DEPRECATED] The `--path` flag is deprecated because 39 | # it relies on being remembered across bundler invocations, 40 | # which bundler will no longer do in future versions. 41 | # Instead please use `bundle config set --local path './bundle'`, 42 | # and stop using this flag 43 | bundle config --local path './bundle' 44 | bundle install ${ADDTL_BUNDLE_ARGS} 45 | 46 | echo "---> Cleaning up unused ruby gems ..." 47 | bundle clean --verbose 48 | fi 49 | 50 | if [[ "$RAILS_MASTER_KEY" == "" && ! -e config/master.key ]]; then 51 | if [[ -e config/secrets.yml.enc ]]; then 52 | # If the master.key was regenerated while there is already 53 | # an encoded file with secrets, it can only be decoded with the original key. 54 | echo "---> WARNING: overwriting secret.yml.enc" 55 | rm config/secrets.yml.enc 56 | fi 57 | 58 | echo "---> No master key present in environment, generating ..." 59 | EDITOR=/bin/true bin/rails credentials:edit 60 | fi 61 | 62 | popd 63 | 64 | # Remove the .bundle directory before moving the application. 65 | # Otherwise conflicts arise with the .bundle directory created above. 66 | rm -rf .bundle 67 | 68 | if [ -x "$ASSEMBLE_SCRIPT" ]; then 69 | $ASSEMBLE_SCRIPT 70 | fi 71 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | git_source(:github) do |repo_name| 4 | repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/") 5 | "https://github.com/#{repo_name}.git" 6 | end 7 | 8 | 9 | # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' 10 | gem 'rails', '~> 6' 11 | # Support postgresql as a database for Active Record 12 | gem 'pg', '~> 1.2.0' 13 | # Support sqlite3 as a database for Active Record 14 | gem 'sqlite3' 15 | # Support redis as a key-value store for Action Cable 16 | gem 'redis' 17 | # Use Puma as the app server 18 | gem 'puma' 19 | # Use SCSS for stylesheets 20 | gem 'sass-rails' 21 | # Use Uglifier as compressor for JavaScript assets 22 | gem 'uglifier' 23 | # See https://github.com/rails/execjs#readme for more supported runtimes 24 | # gem 'therubyracer', platforms: :ruby 25 | 26 | # Use CoffeeScript for .coffee assets and views 27 | gem 'coffee-rails' 28 | # Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks 29 | gem 'turbolinks' 30 | # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder 31 | gem 'jbuilder' 32 | # Use Redis adapter to run Action Cable in production 33 | # gem 'redis', '~> 3.0' 34 | # Use ActiveModel has_secure_password 35 | # gem 'bcrypt', '~> 3.1.7' 36 | 37 | # Use Capistrano for deployment 38 | # gem 'capistrano-rails', group: :development 39 | 40 | gem 'listen' 41 | 42 | gem 'ffi', '>= 1.15.1' 43 | 44 | # ActiveRecord makes use of these bundled gems, as of Ruby 3.1, these requirements 45 | # have to be explicitly marked in a Gemfile. 46 | gem 'matrix' 47 | gem 'net-smtp' 48 | 49 | group :development, :test do 50 | # Call 'byebug' anywhere in the code to stop execution and get a debugger console 51 | gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] 52 | # Adds support for Capybara system testing and selenium driver 53 | gem 'capybara' 54 | gem 'selenium-webdriver' 55 | end 56 | 57 | group :development do 58 | # Access an IRB console on exception pages or by using <%= console %> anywhere in the code. 59 | gem 'web-console' 60 | # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring 61 | gem 'spring' 62 | gem 'spring-watcher-listen' 63 | end 64 | 65 | # Windows does not include zoneinfo files, so bundle the tzinfo-data gem 66 | gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby] 67 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | actioncable (6.1.7.6) 5 | actionpack (= 6.1.7.6) 6 | activesupport (= 6.1.7.6) 7 | nio4r (~> 2.0) 8 | websocket-driver (>= 0.6.1) 9 | actionmailbox (6.1.7.6) 10 | actionpack (= 6.1.7.6) 11 | activejob (= 6.1.7.6) 12 | activerecord (= 6.1.7.6) 13 | activestorage (= 6.1.7.6) 14 | activesupport (= 6.1.7.6) 15 | mail (>= 2.7.1) 16 | actionmailer (6.1.7.6) 17 | actionpack (= 6.1.7.6) 18 | actionview (= 6.1.7.6) 19 | activejob (= 6.1.7.6) 20 | activesupport (= 6.1.7.6) 21 | mail (~> 2.5, >= 2.5.4) 22 | rails-dom-testing (~> 2.0) 23 | actionpack (6.1.7.6) 24 | actionview (= 6.1.7.6) 25 | activesupport (= 6.1.7.6) 26 | rack (~> 2.0, >= 2.0.9) 27 | rack-test (>= 0.6.3) 28 | rails-dom-testing (~> 2.0) 29 | rails-html-sanitizer (~> 1.0, >= 1.2.0) 30 | actiontext (6.1.7.6) 31 | actionpack (= 6.1.7.6) 32 | activerecord (= 6.1.7.6) 33 | activestorage (= 6.1.7.6) 34 | activesupport (= 6.1.7.6) 35 | nokogiri (>= 1.8.5) 36 | actionview (6.1.7.6) 37 | activesupport (= 6.1.7.6) 38 | builder (~> 3.1) 39 | erubi (~> 1.4) 40 | rails-dom-testing (~> 2.0) 41 | rails-html-sanitizer (~> 1.1, >= 1.2.0) 42 | activejob (6.1.7.6) 43 | activesupport (= 6.1.7.6) 44 | globalid (>= 0.3.6) 45 | activemodel (6.1.7.6) 46 | activesupport (= 6.1.7.6) 47 | activerecord (6.1.7.6) 48 | activemodel (= 6.1.7.6) 49 | activesupport (= 6.1.7.6) 50 | activestorage (6.1.7.6) 51 | actionpack (= 6.1.7.6) 52 | activejob (= 6.1.7.6) 53 | activerecord (= 6.1.7.6) 54 | activesupport (= 6.1.7.6) 55 | marcel (~> 1.0) 56 | mini_mime (>= 1.1.0) 57 | activesupport (6.1.7.6) 58 | concurrent-ruby (~> 1.0, >= 1.0.2) 59 | i18n (>= 1.6, < 2) 60 | minitest (>= 5.1) 61 | tzinfo (~> 2.0) 62 | zeitwerk (~> 2.3) 63 | addressable (2.8.6) 64 | public_suffix (>= 2.0.2, < 6.0) 65 | bindex (0.8.1) 66 | builder (3.2.4) 67 | byebug (11.1.3) 68 | capybara (3.35.3) 69 | addressable 70 | mini_mime (>= 0.1.3) 71 | nokogiri (~> 1.8) 72 | rack (>= 1.6.0) 73 | rack-test (>= 0.6.3) 74 | regexp_parser (>= 1.5, < 3.0) 75 | xpath (~> 3.2) 76 | childprocess (3.0.0) 77 | coffee-rails (5.0.0) 78 | coffee-script (>= 2.2.0) 79 | railties (>= 5.2.0) 80 | coffee-script (2.4.1) 81 | coffee-script-source 82 | execjs 83 | coffee-script-source (1.12.2) 84 | concurrent-ruby (1.2.2) 85 | connection_pool (2.4.1) 86 | crass (1.0.6) 87 | digest (3.1.1) 88 | erubi (1.12.0) 89 | execjs (2.9.1) 90 | ffi (1.16.3) 91 | globalid (1.2.1) 92 | activesupport (>= 6.1) 93 | i18n (1.14.1) 94 | concurrent-ruby (~> 1.0) 95 | io-wait (0.3.1) 96 | jbuilder (2.11.5) 97 | actionview (>= 5.0.0) 98 | activesupport (>= 5.0.0) 99 | listen (3.8.0) 100 | rb-fsevent (~> 0.10, >= 0.10.3) 101 | rb-inotify (~> 0.9, >= 0.9.10) 102 | loofah (2.22.0) 103 | crass (~> 1.0.2) 104 | nokogiri (>= 1.12.0) 105 | mail (2.8.1) 106 | mini_mime (>= 0.1.1) 107 | net-imap 108 | net-pop 109 | net-smtp 110 | marcel (1.0.2) 111 | matrix (0.4.2) 112 | method_source (1.0.0) 113 | mini_mime (1.1.2) 114 | mini_portile2 (2.6.1) 115 | minitest (5.15.0) 116 | net-imap (0.2.2) 117 | digest 118 | net-protocol 119 | strscan 120 | net-pop (0.1.2) 121 | net-protocol 122 | net-protocol (0.1.2) 123 | io-wait 124 | timeout 125 | net-smtp (0.3.0) 126 | digest 127 | net-protocol 128 | timeout 129 | nio4r (2.7.0) 130 | nokogiri (1.12.5) 131 | mini_portile2 (~> 2.6.1) 132 | racc (~> 1.4) 133 | pg (1.2.3) 134 | public_suffix (4.0.7) 135 | puma (6.4.0) 136 | nio4r (~> 2.0) 137 | racc (1.7.3) 138 | rack (2.2.8) 139 | rack-test (2.1.0) 140 | rack (>= 1.3) 141 | rails (6.1.7.6) 142 | actioncable (= 6.1.7.6) 143 | actionmailbox (= 6.1.7.6) 144 | actionmailer (= 6.1.7.6) 145 | actionpack (= 6.1.7.6) 146 | actiontext (= 6.1.7.6) 147 | actionview (= 6.1.7.6) 148 | activejob (= 6.1.7.6) 149 | activemodel (= 6.1.7.6) 150 | activerecord (= 6.1.7.6) 151 | activestorage (= 6.1.7.6) 152 | activesupport (= 6.1.7.6) 153 | bundler (>= 1.15.0) 154 | railties (= 6.1.7.6) 155 | sprockets-rails (>= 2.0.0) 156 | rails-dom-testing (2.2.0) 157 | activesupport (>= 5.0.0) 158 | minitest 159 | nokogiri (>= 1.6) 160 | rails-html-sanitizer (1.5.0) 161 | loofah (~> 2.19, >= 2.19.1) 162 | railties (6.1.7.6) 163 | actionpack (= 6.1.7.6) 164 | activesupport (= 6.1.7.6) 165 | method_source 166 | rake (>= 12.2) 167 | thor (~> 1.0) 168 | rake (13.1.0) 169 | rb-fsevent (0.11.2) 170 | rb-inotify (0.10.1) 171 | ffi (~> 1.0) 172 | redis (5.0.8) 173 | redis-client (>= 0.17.0) 174 | redis-client (0.19.1) 175 | connection_pool 176 | regexp_parser (2.8.3) 177 | rubyzip (2.3.2) 178 | sass-rails (6.0.0) 179 | sassc-rails (~> 2.1, >= 2.1.1) 180 | sassc (2.4.0) 181 | ffi (~> 1.9) 182 | sassc-rails (2.1.2) 183 | railties (>= 4.0.0) 184 | sassc (>= 2.0) 185 | sprockets (> 3.0) 186 | sprockets-rails 187 | tilt 188 | selenium-webdriver (3.142.7) 189 | childprocess (>= 0.5, < 4.0) 190 | rubyzip (>= 1.2.2) 191 | spring (2.1.1) 192 | spring-watcher-listen (2.0.1) 193 | listen (>= 2.7, < 4.0) 194 | spring (>= 1.2, < 3.0) 195 | sprockets (4.2.1) 196 | concurrent-ruby (~> 1.0) 197 | rack (>= 2.2.4, < 4) 198 | sprockets-rails (3.4.2) 199 | actionpack (>= 5.2) 200 | activesupport (>= 5.2) 201 | sprockets (>= 3.0.0) 202 | sqlite3 (1.4.4) 203 | strscan (3.0.7) 204 | thor (1.2.2) 205 | tilt (2.3.0) 206 | timeout (0.4.0) 207 | turbolinks (5.2.1) 208 | turbolinks-source (~> 5.2) 209 | turbolinks-source (5.2.0) 210 | tzinfo (2.0.6) 211 | concurrent-ruby (~> 1.0) 212 | uglifier (4.2.0) 213 | execjs (>= 0.3.0, < 3) 214 | web-console (4.2.1) 215 | actionview (>= 6.0.0) 216 | activemodel (>= 6.0.0) 217 | bindex (>= 0.4.0) 218 | railties (>= 6.0.0) 219 | websocket-driver (0.7.6) 220 | websocket-extensions (>= 0.1.0) 221 | websocket-extensions (0.1.5) 222 | xpath (3.2.0) 223 | nokogiri (~> 1.8) 224 | zeitwerk (2.6.12) 225 | 226 | PLATFORMS 227 | ruby 228 | 229 | DEPENDENCIES 230 | byebug 231 | capybara 232 | coffee-rails 233 | ffi (>= 1.15.1) 234 | jbuilder 235 | listen 236 | matrix 237 | net-smtp 238 | pg (~> 1.2.0) 239 | puma 240 | rails (~> 6) 241 | redis 242 | sass-rails 243 | selenium-webdriver 244 | spring 245 | spring-watcher-listen 246 | sqlite3 247 | turbolinks 248 | tzinfo-data 249 | uglifier 250 | web-console 251 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: test-openshift-pytest 2 | test-openshift-pytest: 3 | cd tests && PYTHONPATH=$(CURDIR) python3.12 -m pytest -s -rA --showlocals -vv test_*.py 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | - [Rails Sample App on OpenShift](#rails-sample-app-on-openshift) 6 | * [OpenShift Considerations](#openshift-considerations) 7 | + [Assets](#assets) 8 | + [Security](#security) 9 | + [Development mode](#development-mode) 10 | + [Installation](#installation) 11 | + [Debugging Unexpected Failures](#debugging-unexpected-failures) 12 | + [Adding Webhooks and Making Code Changes](#adding-webhooks-and-making-code-changes) 13 | + [Enabling the Blog example](#enabling-the-blog-example) 14 | + [Hot Deploy](#hot-deploy) 15 | + [Compatibility](#compatibility) 16 | + [License](#license) 17 | 18 | 19 | 20 | Rails Sample App on OpenShift 21 | ============================ 22 | 23 | This is a quickstart Rails application for OpenShift v3 that you can use as a starting point to develop your own application and deploy it on an [OpenShift](https://github.com/openshift/origin) cluster. 24 | 25 | If you'd like to install it, follow [these directions](https://github.com/sclorg/rails-ex/blob/master/README.md#installation). 26 | 27 | The steps in this document assume that you have access to an OpenShift deployment that you can deploy applications on. 28 | 29 | OpenShift Considerations 30 | ------------------------ 31 | These are some special considerations you may need to keep in mind when running your application on OpenShift. 32 | 33 | ### Assets 34 | Your application is set to precompile the assets every time you push to OpenShift. 35 | Any assets you commit to your repo will be preserved alongside those which are generated during the build. 36 | 37 | By adding the ```DISABLE_ASSET_COMPILATION=true``` environment variable value to your BuildConfig, you will disable asset compilation upon application deployment. See the [Basic Build Operations](https://docs.okd.io/latest/dev_guide/builds/basic_build_operations.html#starting-a-build) documentation on setting environment variables for builds in OpenShift V3. 38 | 39 | ### Security 40 | Since these quickstarts are shared code, we had to take special consideration to ensure that security related configuration variables are unique across applications. To accomplish this, we modified some of the configuration files. Now instead of using the same default values, OpenShift can generate these values using the generate from logic defined within the template. 41 | 42 | OpenShift stores these generated values in configuration files that only exist for your deployed application and not in your code anywhere. Each of them will be unique so initialize_secret(:a) will differ from initialize_secret(:b) but they will also be consistent, so any time your application uses them (even across reboots), you know they will be the same. 43 | 44 | TLDR: OpenShift can generate and expose environment variables to your application automatically. Look at this quickstart for an example. 45 | 46 | ### Development mode 47 | When you develop your Rails application in OpenShift, you can also enable the 'development' environment by setting the RAILS_ENV environment variable for your deploymentConfiguration, using the `oc` client, like: 48 | 49 | $ oc set env dc/rails-postgresql-example RAILS_ENV=development 50 | 51 | 52 | If you do so, OpenShift will run your application under 'development' mode. In development mode, your application will: 53 | * Show more detailed errors in the browser 54 | * Skip static assets (re)compilation 55 | 56 | Development environment can help you debug problems in your application in the same way as you do when developing on your local machine. However, we strongly advise you to not run your application in this mode in production. 57 | 58 | ### Installation 59 | These steps assume your OpenShift deployment has the default set of ImageStreams defined. Instructions for installing the default ImageStreams are available [here](https://docs.okd.io/latest/install_config/imagestreams_templates.html). If you are defining the set of ImageStreams now, remember to pass in the proper cluster-admin credentials and to create the ImageStreams in the 'openshift' namespace. 60 | 61 | 1. Fork a copy of [rails-ex](https://github.com/sclorg/rails-ex) 62 | 2. Clone your repository to your development machine and cd to the repository directory 63 | 3. Add a Ruby application from the rails template: 64 | 65 | $ oc new-app openshift/templates/rails-postgresql.json -p SOURCE_REPOSITORY_URL=https://github.com/< yourusername >/rails-ex 66 | 67 | 4. Depending on the state of your system, and whether additional items need to be downloaded, it may take around a minute for your build to be started automatically. If you do not want to wait, run 68 | 69 | $ oc start-build rails-postgresql-example 70 | 71 | 5. Once the build is running, watch your build progress 72 | 73 | $ oc logs build/rails-postgresql-example-1 74 | 75 | 6. Wait for rails-postgresql-example pods to start up (this can take a few minutes): 76 | 77 | $ oc get pods -w 78 | 79 | 80 | Sample output: 81 | 82 | NAME READY REASON RESTARTS AGE 83 | postgresql-1-vk6ny 1/1 Running 0 4m 84 | rails-postgresql-example-1-build 0/1 ExitCode:0 0 3m 85 | rails-postgresql-example-1-deploy 1/1 Running 0 34s 86 | rails-postgresql-example-1-prehook 0/1 ExitCode:0 0 32s 87 | 88 | 89 | 90 | 7. Check the IP and port the rails-postgresql-example service is running on: 91 | 92 | $ oc get svc 93 | 94 | 95 | Sample output: 96 | 97 | NAME LABELS SELECTOR IP(S) PORT(S) 98 | postgresql template=rails-postgresql-example name=postgresql 172.30.197.40 5432/TCP 99 | rails-postgresql-example template=rails-postgresql-example name=rails-postgresql-example 172.30.205.117 8080/TCP 100 | 101 | 102 | In this case, the IP for rails-postgresql-example rails-postgresql-example is 172.30.205.117 and it is on port 8080. 103 | *Note*: you can also get this information from the web console. 104 | 105 | 106 | ### Debugging Unexpected Failures 107 | 108 | Review some of the common tips and suggestions [here](https://github.com/openshift/origin/blob/master/docs/debugging-openshift.md). 109 | 110 | ### Adding Webhooks and Making Code Changes 111 | Since OpenShift V3 does not provide a git repository out of the box, you can configure your github repository to make a webhook call whenever you push your code. 112 | 113 | 1. From the Web Console homepage, navigate to your project 114 | 2. Click on Browse > Builds 115 | 3. Click the link with your BuildConfig name 116 | 4. Click the Configuration tab 117 | 5. Click the "Copy to clipboard" icon to the right of the "GitHub webhook URL" field 118 | 6. Navigate to your repository on GitHub and click on repository settings > webhooks > Add webhook 119 | 7. Paste your webhook URL provided by OpenShift 120 | 8. Leave the defaults for the remaining fields - That's it! 121 | 9. After you save your webhook, if you refresh your settings page you can see the status of the ping that Github sent to OpenShift to verify it can reach the server. 122 | 123 | ### Enabling the Blog example 124 | In order to access the example blog application, you have to remove the 125 | `public/index.html` which serves as the welcome page and rebuild the application. 126 | Another option is to make a request directly to `/articles` which will give you access to the blog. 127 | 128 | The username/pw used for authentication in this application are openshift/secret. 129 | 130 | ### Hot Deploy 131 | 132 | In order to dynamically pick up changes made in your application source code, you need to set the `RAILS_ENV=development` parameter to the [oc new-app](https://docs.okd.io/latest/cli_reference/basic_cli_operations.html#basic-cli-operations) command, while performing the [installation steps](https://github.com/sclorg/rails-ex#installation) described in this README. 133 | 134 | $ oc new-app openshift/templates/rails-postgresql.json -p RAILS_ENV=development 135 | 136 | To change your source code in the running container you need to [oc rsh](https://docs.okd.io/latest/cli_reference/basic_cli_operations.html#troubleshooting-and-debugging-cli-operations) into it. 137 | 138 | $ oc rsh 139 | 140 | After you [oc rsh](https://docs.okd.io/latest/cli_reference/basic_cli_operations.html#troubleshooting-and-debugging-cli-operations) into the running container, your current directory is set to `/opt/app-root/src`, where the source code is located. 141 | 142 | To set your application back to the `production` environment you need to remove `RAILS_ENV` environment variable: 143 | 144 | $ oc set env dc/rails-postgresql-example RAILS_ENV- 145 | 146 | A redeploy will happen automatically due to the `ConfigChange` trigger. 147 | 148 | **NOTICE: If the `ConfigChange` trigger is not set, you need to run the redeploy manually:** 149 | 150 | $ oc deploy rails-postgresql-example --latest 151 | 152 | ### Compatibility 153 | 154 | This repository is compatible with Ruby 2.3 and higher, excluding any alpha or beta versions. 155 | 156 | ### License 157 | This code is dedicated to the public domain to the maximum extent permitted by applicable law, pursuant to [CC0](http://creativecommons.org/publicdomain/zero/1.0/). 158 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require_relative 'config/application' 5 | 6 | Rails.application.load_tasks 7 | -------------------------------------------------------------------------------- /app/assets/config/manifest.js: -------------------------------------------------------------------------------- 1 | //= link_tree ../images 2 | //= link_directory ../javascripts .js 3 | //= link_directory ../stylesheets .css 4 | -------------------------------------------------------------------------------- /app/assets/images/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sclorg/rails-ex/482ef27972d3f594b1e3a1481c1113075238496d/app/assets/images/.keep -------------------------------------------------------------------------------- /app/assets/javascripts/application.js: -------------------------------------------------------------------------------- 1 | // This is a manifest file that'll be compiled into application.js, which will include all the files 2 | // listed below. 3 | // 4 | // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, or any plugin's 5 | // vendor/assets/javascripts directory can be referenced here using a relative path. 6 | // 7 | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the 8 | // compiled file. JavaScript code in this file should be added after the last require_* statement. 9 | // 10 | // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details 11 | // about supported directives. 12 | // 13 | //= require rails-ujs 14 | //= require turbolinks 15 | //= require_tree . 16 | -------------------------------------------------------------------------------- /app/assets/javascripts/articles.coffee: -------------------------------------------------------------------------------- 1 | # Place all the behaviors and hooks related to the matching controller here. 2 | # All this logic will automatically be available in application.js. 3 | # You can use CoffeeScript in this file: http://coffeescript.org/ 4 | -------------------------------------------------------------------------------- /app/assets/javascripts/cable.js: -------------------------------------------------------------------------------- 1 | // Action Cable provides the framework to deal with WebSockets in Rails. 2 | // You can generate new channels where WebSocket features live using the `rails generate channel` command. 3 | // 4 | //= require action_cable 5 | //= require_self 6 | //= require_tree ./channels 7 | 8 | (function() { 9 | this.App || (this.App = {}); 10 | 11 | App.cable = ActionCable.createConsumer(); 12 | 13 | }).call(this); 14 | -------------------------------------------------------------------------------- /app/assets/javascripts/channels/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sclorg/rails-ex/482ef27972d3f594b1e3a1481c1113075238496d/app/assets/javascripts/channels/.keep -------------------------------------------------------------------------------- /app/assets/javascripts/comments.coffee: -------------------------------------------------------------------------------- 1 | # Place all the behaviors and hooks related to the matching controller here. 2 | # All this logic will automatically be available in application.js. 3 | # You can use CoffeeScript in this file: http://coffeescript.org/ 4 | -------------------------------------------------------------------------------- /app/assets/javascripts/welcome.coffee: -------------------------------------------------------------------------------- 1 | # Place all the behaviors and hooks related to the matching controller here. 2 | # All this logic will automatically be available in application.js. 3 | # You can use CoffeeScript in this file: http://coffeescript.org/ 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/application.css: -------------------------------------------------------------------------------- 1 | /* 2 | * This is a manifest file that'll be compiled into application.css, which will include all the files 3 | * listed below. 4 | * 5 | * Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's 6 | * vendor/assets/stylesheets directory can be referenced here using a relative path. 7 | * 8 | * You're free to add application-wide styles to this file and they'll appear at the bottom of the 9 | * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS 10 | * files in this directory. Styles in this file should be added after the last require_* statement. 11 | * It is generally better to create a new file per style scope. 12 | * 13 | *= require_tree . 14 | *= require_self 15 | */ 16 | -------------------------------------------------------------------------------- /app/assets/stylesheets/articles.scss: -------------------------------------------------------------------------------- 1 | // Place all the styles related to the Articles controller here. 2 | // They will automatically be included in application.css. 3 | // You can use Sass (SCSS) here: http://sass-lang.com/ 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/comments.scss: -------------------------------------------------------------------------------- 1 | // Place all the styles related to the Comments controller here. 2 | // They will automatically be included in application.css. 3 | // You can use Sass (SCSS) here: http://sass-lang.com/ 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/scaffolds.scss: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #fff; 3 | color: #333; 4 | font-family: verdana, arial, helvetica, sans-serif; 5 | font-size: 13px; 6 | line-height: 18px; 7 | margin: 33px; 8 | } 9 | 10 | p, ol, ul, td { 11 | font-family: verdana, arial, helvetica, sans-serif; 12 | font-size: 13px; 13 | line-height: 18px; 14 | margin: 33px; 15 | } 16 | 17 | pre { 18 | background-color: #eee; 19 | padding: 10px; 20 | font-size: 11px; 21 | } 22 | 23 | a { 24 | color: #000; 25 | 26 | &:visited { 27 | color: #666; 28 | } 29 | 30 | &:hover { 31 | color: #fff; 32 | background-color: #000; 33 | } 34 | } 35 | 36 | th { 37 | padding-bottom: 5px; 38 | } 39 | 40 | td { 41 | padding-bottom: 7px; 42 | padding-left: 5px; 43 | padding-right: 5px; 44 | } 45 | 46 | div { 47 | &.field, &.actions { 48 | margin-bottom: 10px; 49 | } 50 | } 51 | 52 | #notice { 53 | color: green; 54 | } 55 | 56 | .field_with_errors { 57 | padding: 2px; 58 | background-color: red; 59 | display: table; 60 | } 61 | 62 | #error_explanation { 63 | width: 450px; 64 | border: 2px solid red; 65 | padding: 7px; 66 | padding-bottom: 0; 67 | margin-bottom: 20px; 68 | background-color: #f0f0f0; 69 | 70 | h2 { 71 | text-align: left; 72 | font-weight: bold; 73 | padding: 5px 5px 5px 15px; 74 | font-size: 12px; 75 | margin: -7px; 76 | margin-bottom: 0; 77 | background-color: #c00; 78 | color: #fff; 79 | } 80 | 81 | ul li { 82 | font-size: 12px; 83 | list-style: square; 84 | } 85 | } 86 | 87 | label { 88 | display: block; 89 | } 90 | -------------------------------------------------------------------------------- /app/assets/stylesheets/welcome.scss: -------------------------------------------------------------------------------- 1 | // Place all the styles related to the Welcome controller here. 2 | // They will automatically be included in application.css. 3 | // You can use Sass (SCSS) here: http://sass-lang.com/ 4 | -------------------------------------------------------------------------------- /app/channels/application_cable/channel.rb: -------------------------------------------------------------------------------- 1 | module ApplicationCable 2 | class Channel < ActionCable::Channel::Base 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/channels/application_cable/connection.rb: -------------------------------------------------------------------------------- 1 | module ApplicationCable 2 | class Connection < ActionCable::Connection::Base 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | protect_from_forgery with: :exception 3 | end 4 | -------------------------------------------------------------------------------- /app/controllers/articles_controller.rb: -------------------------------------------------------------------------------- 1 | class ArticlesController < ApplicationController 2 | 3 | http_basic_authenticate_with name: (ENV["APPLICATION_USER"].blank? ? 'test' : ENV['APPLICATION_USER']), password: (ENV["APPLICATION_PASSWORD"].blank? ? 'test' : ENV["APPLICATION_PASSWORD"]), except: [:index, :show] 4 | 5 | before_action :set_article, only: [:show, :edit, :update, :destroy] 6 | 7 | # GET /articles 8 | # GET /articles.json 9 | def index 10 | @articles = Article.all 11 | end 12 | 13 | # GET /articles/1 14 | # GET /articles/1.json 15 | def show 16 | end 17 | 18 | # GET /articles/new 19 | def new 20 | @article = Article.new 21 | end 22 | 23 | # GET /articles/1/edit 24 | def edit 25 | end 26 | 27 | # POST /articles 28 | # POST /articles.json 29 | def create 30 | @article = Article.new(article_params) 31 | 32 | respond_to do |format| 33 | if @article.save 34 | format.html { redirect_to @article, notice: 'Article was successfully created.' } 35 | format.json { render :show, status: :created, location: @article } 36 | else 37 | format.html { render :new } 38 | format.json { render json: @article.errors, status: :unprocessable_entity } 39 | end 40 | end 41 | end 42 | 43 | # PATCH/PUT /articles/1 44 | # PATCH/PUT /articles/1.json 45 | def update 46 | respond_to do |format| 47 | if @article.update(article_params) 48 | format.html { redirect_to @article, notice: 'Article was successfully updated.' } 49 | format.json { render :show, status: :ok, location: @article } 50 | else 51 | format.html { render :edit } 52 | format.json { render json: @article.errors, status: :unprocessable_entity } 53 | end 54 | end 55 | end 56 | 57 | # DELETE /articles/1 58 | # DELETE /articles/1.json 59 | def destroy 60 | @article.destroy 61 | respond_to do |format| 62 | format.html { redirect_to articles_url, notice: 'Article was successfully destroyed.' } 63 | format.json { head :no_content } 64 | end 65 | end 66 | 67 | private 68 | # Use callbacks to share common setup or constraints between actions. 69 | def set_article 70 | @article = Article.find(params[:id]) 71 | end 72 | 73 | # Never trust parameters from the scary internet, only allow the white list through. 74 | def article_params 75 | params.require(:article).permit(:title, :body) 76 | end 77 | end 78 | -------------------------------------------------------------------------------- /app/controllers/comments_controller.rb: -------------------------------------------------------------------------------- 1 | class CommentsController < ApplicationController 2 | 3 | http_basic_authenticate_with name: (ENV["APPLICATION_USER"].blank? ? 'test' : ENV['APPLICATION_USER']), password: (ENV["APPLICATION_PASSWORD"].blank? ? 'test' : ENV["APPLICATION_PASSWORD"]), only: :destroy 4 | 5 | before_action :set_comment, only: [:show, :edit, :update, :destroy] 6 | 7 | # GET /comments 8 | # GET /comments.json 9 | def index 10 | @comments = Comment.all 11 | end 12 | 13 | # GET /comments/1 14 | # GET /comments/1.json 15 | def show 16 | end 17 | 18 | # GET /comments/new 19 | def new 20 | @comment = Comment.new 21 | end 22 | 23 | # GET /comments/1/edit 24 | def edit 25 | end 26 | 27 | # POST /comments 28 | # POST /comments.json 29 | def create 30 | @article = Article.find(params[:article_id]) 31 | @comment = @article.comments.create(comment_params) 32 | 33 | respond_to do |format| 34 | if @comment.save 35 | format.html { redirect_to article_path(@article), notice: 'Comment was successfully created.' } 36 | format.json { render :show, status: :created, location: @comment } 37 | else 38 | format.html { render :new } 39 | format.json { render json: @comment.errors, status: :unprocessable_entity } 40 | end 41 | end 42 | end 43 | 44 | # PATCH/PUT /comments/1 45 | # PATCH/PUT /comments/1.json 46 | def update 47 | respond_to do |format| 48 | if @comment.update(comment_params) 49 | format.html { redirect_to @comment, notice: 'Comment was successfully updated.' } 50 | format.json { render :show, status: :ok, location: @comment } 51 | else 52 | format.html { render :edit } 53 | format.json { render json: @comment.errors, status: :unprocessable_entity } 54 | end 55 | end 56 | end 57 | 58 | # DELETE /comments/1 59 | # DELETE /comments/1.json 60 | def destroy 61 | @comment.destroy 62 | respond_to do |format| 63 | format.html { redirect_to comments_url, notice: 'Comment was successfully destroyed.' } 64 | format.json { head :no_content } 65 | end 66 | end 67 | 68 | private 69 | # Use callbacks to share common setup or constraints between actions. 70 | def set_comment 71 | @comment = Comment.find(params[:id]) 72 | end 73 | 74 | # Never trust parameters from the scary internet, only allow the white list through. 75 | def comment_params 76 | params.require(:comment).permit(:commenter, :body) 77 | end 78 | end 79 | -------------------------------------------------------------------------------- /app/controllers/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sclorg/rails-ex/482ef27972d3f594b1e3a1481c1113075238496d/app/controllers/concerns/.keep -------------------------------------------------------------------------------- /app/controllers/welcome_controller.rb: -------------------------------------------------------------------------------- 1 | class WelcomeController < ApplicationController 2 | def index 3 | render :file => 'public/index.html' 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | module ApplicationHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/articles_helper.rb: -------------------------------------------------------------------------------- 1 | module ArticlesHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/comments_helper.rb: -------------------------------------------------------------------------------- 1 | module CommentsHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/welcome_helper.rb: -------------------------------------------------------------------------------- 1 | module WelcomeHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/jobs/application_job.rb: -------------------------------------------------------------------------------- 1 | class ApplicationJob < ActiveJob::Base 2 | end 3 | -------------------------------------------------------------------------------- /app/mailers/application_mailer.rb: -------------------------------------------------------------------------------- 1 | class ApplicationMailer < ActionMailer::Base 2 | default from: 'from@example.com' 3 | layout 'mailer' 4 | end 5 | -------------------------------------------------------------------------------- /app/models/application_record.rb: -------------------------------------------------------------------------------- 1 | class ApplicationRecord < ActiveRecord::Base 2 | self.abstract_class = true 3 | end 4 | -------------------------------------------------------------------------------- /app/models/article.rb: -------------------------------------------------------------------------------- 1 | class Article < ApplicationRecord 2 | has_many :comments, dependent: :destroy 3 | validates :title, presence: true, length: { minimum: 5 } 4 | end 5 | -------------------------------------------------------------------------------- /app/models/comment.rb: -------------------------------------------------------------------------------- 1 | class Comment < ApplicationRecord 2 | belongs_to :article 3 | end 4 | -------------------------------------------------------------------------------- /app/models/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sclorg/rails-ex/482ef27972d3f594b1e3a1481c1113075238496d/app/models/concerns/.keep -------------------------------------------------------------------------------- /app/views/articles/_article.json.jbuilder: -------------------------------------------------------------------------------- 1 | json.extract! article, :id, :title, :body, :created_at, :updated_at 2 | json.url article_url(article, format: :json) -------------------------------------------------------------------------------- /app/views/articles/_form.html.erb: -------------------------------------------------------------------------------- 1 | <%= form_for(article) do |f| %> 2 | <% if article.errors.any? %> 3 |
4 |

<%= pluralize(article.errors.count, "error") %> prohibited this article from being saved:

5 | 6 | 11 |
12 | <% end %> 13 | 14 |
15 | <%= f.label :title %> 16 | <%= f.text_field :title %> 17 |
18 | 19 |
20 | <%= f.label :body %> 21 | <%= f.text_area :body %> 22 |
23 | 24 |
25 | <%= f.submit %> 26 |
27 | <% end %> 28 | -------------------------------------------------------------------------------- /app/views/articles/edit.html.erb: -------------------------------------------------------------------------------- 1 |

Editing Article

2 | 3 | <%= render 'form', article: @article %> 4 | 5 | <%= link_to 'Show', @article %> | 6 | <%= link_to 'Back', articles_path %> 7 | -------------------------------------------------------------------------------- /app/views/articles/index.html.erb: -------------------------------------------------------------------------------- 1 |

<%= notice %>

2 | 3 |

Listing articles

4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | <% @articles.each do |article| %> 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | <% end %> 24 | 25 |
TitleBody
<%= article.title %><%= article.body %><%= link_to 'Show', article %><%= link_to 'Edit', edit_article_path(article) %><%= link_to 'Destroy', article, method: :delete, data: { confirm: 'Are you sure?' } %>
26 | 27 |
28 | 29 | <%= link_to 'New Article', new_article_path %> 30 | -------------------------------------------------------------------------------- /app/views/articles/index.json.jbuilder: -------------------------------------------------------------------------------- 1 | json.array! @articles, partial: 'articles/article', as: :article -------------------------------------------------------------------------------- /app/views/articles/new.html.erb: -------------------------------------------------------------------------------- 1 |

New Article

2 | 3 | <%= render 'form', article: @article %> 4 | 5 | <%= link_to 'Back', articles_path %> 6 | -------------------------------------------------------------------------------- /app/views/articles/show.html.erb: -------------------------------------------------------------------------------- 1 |

<%= notice %>

2 | 3 |

4 | Title: 5 | <%= @article.title %> 6 |

7 | 8 |

9 | Body: 10 | <%= @article.body %> 11 |

12 |

Add a comment:

13 | <% @article.comments.each do |comment| %> 14 |

15 | Commenter: 16 | <%= comment.commenter %> 17 |

18 |

19 | Comment: 20 | <%= comment.body %> 21 |

22 | <% end %> 23 | <%= form_for([@article, @article.comments.build]) do |f| %> 24 |

25 | <%= f.label :commenter %>
26 | <%= f.text_field :commenter %> 27 |

28 |

29 | <%= f.label :body %>
30 | <%= f.text_area :body %> 31 |

32 |

33 | <%= f.submit %> 34 |

35 | <% end %> 36 | <%= link_to 'Edit', edit_article_path(@article) %> | 37 | <%= link_to 'Back', articles_path %> 38 | -------------------------------------------------------------------------------- /app/views/articles/show.json.jbuilder: -------------------------------------------------------------------------------- 1 | json.partial! "articles/article", article: @article -------------------------------------------------------------------------------- /app/views/layouts/application.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Welcome to OpenShift 5 | <%= csrf_meta_tags %> 6 | 7 | <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> 8 | <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> 9 | 10 | 11 | 12 | <%= yield %> 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/views/layouts/mailer.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | <%= yield %> 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/views/layouts/mailer.text.erb: -------------------------------------------------------------------------------- 1 | <%= yield %> 2 | -------------------------------------------------------------------------------- /app/views/welcome/index.html.erb: -------------------------------------------------------------------------------- 1 |

Hello, Rails!

2 | <%= link_to 'My Blog', controller: 'articles' %> 3 | -------------------------------------------------------------------------------- /bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | load File.expand_path("spring", __dir__) 3 | APP_PATH = File.expand_path('../config/application', __dir__) 4 | require_relative "../config/boot" 5 | require "rails/commands" 6 | -------------------------------------------------------------------------------- /bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | load File.expand_path("spring", __dir__) 3 | require_relative "../config/boot" 4 | require "rake" 5 | Rake.application.run 6 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require "fileutils" 3 | 4 | # path to your application root. 5 | APP_ROOT = File.expand_path('..', __dir__) 6 | 7 | def system!(*args) 8 | system(*args) || abort("\n== Command #{args} failed ==") 9 | end 10 | 11 | FileUtils.chdir APP_ROOT do 12 | # This script is a way to set up or update your development environment automatically. 13 | # This script is idempotent, so that you can run it at any time and get an expectable outcome. 14 | # Add necessary setup steps to this file. 15 | 16 | puts '== Installing dependencies ==' 17 | system! 'gem install bundler --conservative' 18 | system('bundle check') || system!('bundle install') 19 | 20 | # puts "\n== Copying sample files ==" 21 | # unless File.exist?('config/database.yml') 22 | # FileUtils.cp 'config/database.yml.sample', 'config/database.yml' 23 | # end 24 | 25 | puts "\n== Preparing database ==" 26 | system! 'bin/rails db:prepare' 27 | 28 | puts "\n== Removing old logs and tempfiles ==" 29 | system! 'bin/rails log:clear tmp:clear' 30 | 31 | puts "\n== Restarting application server ==" 32 | system! 'bin/rails restart' 33 | end 34 | -------------------------------------------------------------------------------- /bin/spring: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | if !defined?(Spring) && [nil, "development", "test"].include?(ENV["RAILS_ENV"]) 3 | gem "bundler" 4 | require "bundler" 5 | 6 | # Load Spring without loading other gems in the Gemfile, for speed. 7 | Bundler.locked_gems&.specs&.find { |spec| spec.name == "spring" }&.tap do |spring| 8 | Gem.use_paths Gem.dir, Bundler.bundle_path.to_s, *Gem.path 9 | gem "spring", spring.version 10 | require "spring/binstub" 11 | rescue Gem::LoadError 12 | # Ignore when Spring is not installed. 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /bin/update: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'pathname' 3 | require 'fileutils' 4 | include FileUtils 5 | 6 | # path to your application root. 7 | APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) 8 | 9 | def system!(*args) 10 | system(*args) || abort("\n== Command #{args} failed ==") 11 | end 12 | 13 | chdir APP_ROOT do 14 | # This script is a way to update your development environment automatically. 15 | # Add necessary update steps to this file. 16 | 17 | puts '== Installing dependencies ==' 18 | system! 'gem install bundler --conservative' 19 | system('bundle check') || system!('bundle install') 20 | 21 | puts "\n== Updating database ==" 22 | system! 'bin/rails db:migrate' 23 | 24 | puts "\n== Removing old logs and tempfiles ==" 25 | system! 'bin/rails log:clear tmp:clear' 26 | 27 | puts "\n== Restarting application server ==" 28 | system! 'bin/rails restart' 29 | end 30 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require_relative "config/environment" 4 | 5 | run Rails.application 6 | Rails.application.load_server 7 | -------------------------------------------------------------------------------- /config/application.rb: -------------------------------------------------------------------------------- 1 | require_relative "boot" 2 | 3 | require "rails/all" 4 | 5 | # Require the gems listed in Gemfile, including any gems 6 | # you've limited to :test, :development, or :production. 7 | Bundler.require(*Rails.groups) 8 | 9 | module RailsEx 10 | class Application < Rails::Application 11 | # Initialize configuration defaults for originally generated Rails version. 12 | config.load_defaults 5.1 13 | 14 | # Configuration for the application, engines, and railties goes here. 15 | # 16 | # These settings can be overridden in specific environments using the files 17 | # in config/environments, which are processed later. 18 | # 19 | # config.time_zone = "Central Time (US & Canada)" 20 | # config.eager_load_paths << Rails.root.join("extras") 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /config/boot.rb: -------------------------------------------------------------------------------- 1 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) 2 | 3 | require "bundler/setup" # Set up gems listed in the Gemfile. 4 | -------------------------------------------------------------------------------- /config/cable.yml: -------------------------------------------------------------------------------- 1 | development: 2 | adapter: async 3 | 4 | test: 5 | adapter: test 6 | 7 | production: 8 | adapter: redis 9 | url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> 10 | channel_prefix: rails_ex_production 11 | -------------------------------------------------------------------------------- /config/database.yml: -------------------------------------------------------------------------------- 1 | # PostgreSQL. Versions 8.2 and up are supported. 2 | 3 | <% user = ENV.key?("POSTGRESQL_ADMIN_PASSWORD") ? "root" : ENV["POSTGRESQL_USER"] %> 4 | <% password = ENV.key?("POSTGRESQL_ADMIN_PASSWORD") ? ENV["POSTGRESQL_ADMIN_PASSWORD"] : ENV["POSTGRESQL_PASSWORD"] %> 5 | <% db_service = ENV.fetch("DATABASE_SERVICE_NAME","").upcase %> 6 | 7 | default: &default 8 | adapter: postgresql 9 | encoding: unicode 10 | # For details on connection pooling, see rails configuration guide 11 | # http://guides.rubyonrails.org/configuring.html#database-pooling 12 | pool: <%= ENV["POSTGRESQL_MAX_CONNECTIONS"] || 5 %> 13 | username: <%= user %> 14 | password: <%= password %> 15 | host: <%= ENV["#{db_service}_SERVICE_HOST"] %> 16 | port: <%= ENV["#{db_service}_SERVICE_PORT"] %> 17 | database: <%= ENV["POSTGRESQL_DATABASE"] %> 18 | 19 | development: 20 | <<: *default 21 | 22 | test: 23 | adapter: sqlite3 24 | database: db/test.sqlite3 25 | pool: 5 26 | timeout: 5000 27 | 28 | production: 29 | <<: *default 30 | #database: blog_production 31 | #username: myapp 32 | #password: <%= ENV['MYAPP_DATABASE_PASSWORD'] %> 33 | #host: 34 | #port: 35 | -------------------------------------------------------------------------------- /config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the Rails application. 2 | require_relative "application" 3 | 4 | # Initialize the Rails application. 5 | Rails.application.initialize! 6 | -------------------------------------------------------------------------------- /config/environments/development.rb: -------------------------------------------------------------------------------- 1 | require "active_support/core_ext/integer/time" 2 | 3 | Rails.application.configure do 4 | # Settings specified here will take precedence over those in config/application.rb. 5 | 6 | # In the development environment your application's code is reloaded any time 7 | # it changes. This slows down response time but is perfect for development 8 | # since you don't have to restart the web server when you make code changes. 9 | config.cache_classes = false 10 | 11 | # Do not eager load code on boot. 12 | config.eager_load = false 13 | 14 | # Show full error reports. 15 | config.consider_all_requests_local = true 16 | 17 | # Enable/disable caching. By default caching is disabled. 18 | # Run rails dev:cache to toggle caching. 19 | if Rails.root.join('tmp', 'caching-dev.txt').exist? 20 | config.action_controller.perform_caching = true 21 | config.action_controller.enable_fragment_cache_logging = true 22 | 23 | config.cache_store = :memory_store 24 | config.public_file_server.headers = { 25 | 'Cache-Control' => "public, max-age=#{2.days.to_i}" 26 | } 27 | else 28 | config.action_controller.perform_caching = false 29 | 30 | config.cache_store = :null_store 31 | end 32 | 33 | # Store uploaded files on the local file system (see config/storage.yml for options). 34 | config.active_storage.service = :local 35 | 36 | # Don't care if the mailer can't send. 37 | config.action_mailer.raise_delivery_errors = false 38 | 39 | config.action_mailer.perform_caching = false 40 | 41 | # Print deprecation notices to the Rails logger. 42 | config.active_support.deprecation = :log 43 | 44 | # Raise exceptions for disallowed deprecations. 45 | config.active_support.disallowed_deprecation = :raise 46 | 47 | # Tell Active Support which deprecation messages to disallow. 48 | config.active_support.disallowed_deprecation_warnings = [] 49 | 50 | # Raise an error on page load if there are pending migrations. 51 | config.active_record.migration_error = :page_load 52 | 53 | # Highlight code that triggered database queries in logs. 54 | config.active_record.verbose_query_logs = true 55 | 56 | # Debug mode disables concatenation and preprocessing of assets. 57 | # This option may cause significant delays in view rendering with a large 58 | # number of complex assets. 59 | config.assets.debug = true 60 | 61 | # Suppress logger output for asset requests. 62 | config.assets.quiet = true 63 | 64 | # Raises error for missing translations. 65 | # config.i18n.raise_on_missing_translations = true 66 | 67 | # Annotate rendered view with file names. 68 | # config.action_view.annotate_rendered_view_with_filenames = true 69 | 70 | # Use an evented file watcher to asynchronously detect changes in source code, 71 | # routes, locales, etc. This feature depends on the listen gem. 72 | config.file_watcher = ActiveSupport::EventedFileUpdateChecker 73 | 74 | # Uncomment if you wish to allow Action Cable access from any origin. 75 | # config.action_cable.disable_request_forgery_protection = true 76 | end 77 | -------------------------------------------------------------------------------- /config/environments/production.rb: -------------------------------------------------------------------------------- 1 | require "active_support/core_ext/integer/time" 2 | 3 | Rails.application.configure do 4 | # Settings specified here will take precedence over those in config/application.rb. 5 | 6 | # Code is not reloaded between requests. 7 | config.cache_classes = true 8 | 9 | # Eager load code on boot. This eager loads most of Rails and 10 | # your application in memory, allowing both threaded web servers 11 | # and those relying on copy on write to perform better. 12 | # Rake tasks automatically ignore this option for performance. 13 | config.eager_load = true 14 | 15 | # Full error reports are disabled and caching is turned on. 16 | config.consider_all_requests_local = false 17 | config.action_controller.perform_caching = true 18 | 19 | # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"] 20 | # or in config/master.key. This key is used to decrypt credentials (and other encrypted files). 21 | # config.require_master_key = true 22 | 23 | # Disable serving static files from the `/public` folder by default since 24 | # Apache or NGINX already handles this. 25 | # config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? 26 | config.public_file_server.enabled = true 27 | 28 | # Compress CSS using a preprocessor. 29 | # config.assets.css_compressor = :sass 30 | 31 | # Do not fallback to assets pipeline if a precompiled asset is missed. 32 | config.assets.compile = false 33 | 34 | # Enable serving of images, stylesheets, and JavaScripts from an asset server. 35 | # config.asset_host = 'http://assets.example.com' 36 | 37 | # Specifies the header that your server uses for sending files. 38 | # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache 39 | # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX 40 | 41 | # Store uploaded files on the local file system (see config/storage.yml for options). 42 | config.active_storage.service = :local 43 | 44 | # Mount Action Cable outside main process or domain. 45 | # config.action_cable.mount_path = nil 46 | # config.action_cable.url = 'wss://example.com/cable' 47 | # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ] 48 | 49 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. 50 | # config.force_ssl = true 51 | 52 | # Include generic and useful information about system operation, but avoid logging too much 53 | # information to avoid inadvertent exposure of personally identifiable information (PII). 54 | config.log_level = :info 55 | 56 | # Prepend all log lines with the following tags. 57 | config.log_tags = [ :request_id ] 58 | 59 | # Use a different cache store in production. 60 | # config.cache_store = :mem_cache_store 61 | 62 | # Use a real queuing backend for Active Job (and separate queues per environment). 63 | # config.active_job.queue_adapter = :resque 64 | # config.active_job.queue_name_prefix = "rails_ex_production" 65 | 66 | config.action_mailer.perform_caching = false 67 | 68 | # Ignore bad email addresses and do not raise email delivery errors. 69 | # Set this to true and configure the email server for immediate delivery to raise delivery errors. 70 | # config.action_mailer.raise_delivery_errors = false 71 | 72 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to 73 | # the I18n.default_locale when a translation cannot be found). 74 | config.i18n.fallbacks = true 75 | 76 | # Send deprecation notices to registered listeners. 77 | config.active_support.deprecation = :notify 78 | 79 | # Log disallowed deprecations. 80 | config.active_support.disallowed_deprecation = :log 81 | 82 | # Tell Active Support which deprecation messages to disallow. 83 | config.active_support.disallowed_deprecation_warnings = [] 84 | 85 | # Use default logging formatter so that PID and timestamp are not suppressed. 86 | config.log_formatter = ::Logger::Formatter.new 87 | 88 | # Use a different logger for distributed setups. 89 | # require "syslog/logger" 90 | # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name') 91 | 92 | if ENV["RAILS_LOG_TO_STDOUT"].present? 93 | logger = ActiveSupport::Logger.new(STDOUT) 94 | logger.formatter = config.log_formatter 95 | config.logger = ActiveSupport::TaggedLogging.new(logger) 96 | end 97 | 98 | # Do not dump schema after migrations. 99 | config.active_record.dump_schema_after_migration = false 100 | 101 | # Inserts middleware to perform automatic connection switching. 102 | # The `database_selector` hash is used to pass options to the DatabaseSelector 103 | # middleware. The `delay` is used to determine how long to wait after a write 104 | # to send a subsequent read to the primary. 105 | # 106 | # The `database_resolver` class is used by the middleware to determine which 107 | # database is appropriate to use based on the time delay. 108 | # 109 | # The `database_resolver_context` class is used by the middleware to set 110 | # timestamps for the last write to the primary. The resolver uses the context 111 | # class timestamps to determine how long to wait before reading from the 112 | # replica. 113 | # 114 | # By default Rails will store a last write timestamp in the session. The 115 | # DatabaseSelector middleware is designed as such you can define your own 116 | # strategy for connection switching and pass that into the middleware through 117 | # these configuration options. 118 | # config.active_record.database_selector = { delay: 2.seconds } 119 | # config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver 120 | # config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session 121 | end 122 | -------------------------------------------------------------------------------- /config/environments/test.rb: -------------------------------------------------------------------------------- 1 | require "active_support/core_ext/integer/time" 2 | 3 | # The test environment is used exclusively to run your application's 4 | # test suite. You never need to work with it otherwise. Remember that 5 | # your test database is "scratch space" for the test suite and is wiped 6 | # and recreated between test runs. Don't rely on the data there! 7 | 8 | Rails.application.configure do 9 | # Settings specified here will take precedence over those in config/application.rb. 10 | 11 | config.cache_classes = false 12 | config.action_view.cache_template_loading = true 13 | 14 | # Do not eager load code on boot. This avoids loading your whole application 15 | # just for the purpose of running a single test. If you are using a tool that 16 | # preloads Rails for running tests, you may have to set it to true. 17 | config.eager_load = false 18 | 19 | # Configure public file server for tests with Cache-Control for performance. 20 | config.public_file_server.enabled = true 21 | config.public_file_server.headers = { 22 | 'Cache-Control' => "public, max-age=#{1.hour.to_i}" 23 | } 24 | 25 | # Show full error reports and disable caching. 26 | config.consider_all_requests_local = true 27 | config.action_controller.perform_caching = false 28 | config.cache_store = :null_store 29 | 30 | # Raise exceptions instead of rendering exception templates. 31 | config.action_dispatch.show_exceptions = false 32 | 33 | # Disable request forgery protection in test environment. 34 | config.action_controller.allow_forgery_protection = false 35 | 36 | # Store uploaded files on the local file system in a temporary directory. 37 | config.active_storage.service = :test 38 | 39 | config.action_mailer.perform_caching = false 40 | 41 | # Tell Action Mailer not to deliver emails to the real world. 42 | # The :test delivery method accumulates sent emails in the 43 | # ActionMailer::Base.deliveries array. 44 | config.action_mailer.delivery_method = :test 45 | 46 | # Print deprecation notices to the stderr. 47 | config.active_support.deprecation = :stderr 48 | 49 | # Raise exceptions for disallowed deprecations. 50 | config.active_support.disallowed_deprecation = :raise 51 | 52 | # Tell Active Support which deprecation messages to disallow. 53 | config.active_support.disallowed_deprecation_warnings = [] 54 | 55 | # Raises error for missing translations. 56 | # config.i18n.raise_on_missing_translations = true 57 | 58 | # Annotate rendered view with file names. 59 | # config.action_view.annotate_rendered_view_with_filenames = true 60 | end 61 | -------------------------------------------------------------------------------- /config/initializers/application_controller_renderer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # ActiveSupport::Reloader.to_prepare do 4 | # ApplicationController.renderer.defaults.merge!( 5 | # http_host: 'example.org', 6 | # https: false 7 | # ) 8 | # end 9 | -------------------------------------------------------------------------------- /config/initializers/assets.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Version of your assets, change this if you want to expire all your assets. 4 | Rails.application.config.assets.version = '1.0' 5 | 6 | # Add additional assets to the asset load path. 7 | # Rails.application.config.assets.paths << Emoji.images_path 8 | 9 | # Precompile additional assets. 10 | # application.js, application.css, and all non-JS/CSS in the app/assets 11 | # folder are already added. 12 | # Rails.application.config.assets.precompile += %w( admin.js admin.css ) 13 | -------------------------------------------------------------------------------- /config/initializers/backtrace_silencers.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. 4 | # Rails.backtrace_cleaner.add_silencer { |line| /my_noisy_library/.match?(line) } 5 | 6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code 7 | # by setting BACKTRACE=1 before calling your invocation, like "BACKTRACE=1 ./bin/rails runner 'MyClass.perform'". 8 | Rails.backtrace_cleaner.remove_silencers! if ENV["BACKTRACE"] 9 | -------------------------------------------------------------------------------- /config/initializers/content_security_policy.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Define an application-wide content security policy 4 | # For further information see the following documentation 5 | # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy 6 | 7 | # Rails.application.config.content_security_policy do |policy| 8 | # policy.default_src :self, :https 9 | # policy.font_src :self, :https, :data 10 | # policy.img_src :self, :https, :data 11 | # policy.object_src :none 12 | # policy.script_src :self, :https 13 | # policy.style_src :self, :https 14 | 15 | # # Specify URI for violation reports 16 | # # policy.report_uri "/csp-violation-report-endpoint" 17 | # end 18 | 19 | # If you are using UJS then enable automatic nonce generation 20 | # Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) } 21 | 22 | # Set the nonce only to specific directives 23 | # Rails.application.config.content_security_policy_nonce_directives = %w(script-src) 24 | 25 | # Report CSP violations to a specified URI 26 | # For further information see the following documentation: 27 | # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only 28 | # Rails.application.config.content_security_policy_report_only = true 29 | -------------------------------------------------------------------------------- /config/initializers/cookies_serializer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Specify a serializer for the signed and encrypted cookie jars. 4 | # Valid options are :json, :marshal, and :hybrid. 5 | Rails.application.config.action_dispatch.cookies_serializer = :json 6 | -------------------------------------------------------------------------------- /config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Configure sensitive parameters which will be filtered from the log file. 4 | Rails.application.config.filter_parameters += [ 5 | :passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn 6 | ] 7 | -------------------------------------------------------------------------------- /config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new inflection rules using the following format. Inflections 4 | # are locale specific, and you may define rules for as many different 5 | # locales as you wish. All of these examples are active by default: 6 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 7 | # inflect.plural /^(ox)$/i, '\1en' 8 | # inflect.singular /^(ox)en/i, '\1' 9 | # inflect.irregular 'person', 'people' 10 | # inflect.uncountable %w( fish sheep ) 11 | # end 12 | 13 | # These inflection rules are supported but not enabled by default: 14 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 15 | # inflect.acronym 'RESTful' 16 | # end 17 | -------------------------------------------------------------------------------- /config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new mime types for use in respond_to blocks: 4 | # Mime::Type.register "text/richtext", :rtf 5 | -------------------------------------------------------------------------------- /config/initializers/new_framework_defaults.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | # 3 | # This file contains migration options to ease your Rails 5.0 upgrade. 4 | # 5 | # Read the Rails 5.0 release notes for more info on each option. 6 | 7 | # Enable per-form CSRF tokens. Previous versions had false. 8 | Rails.application.config.action_controller.per_form_csrf_tokens = true 9 | 10 | # Enable origin-checking CSRF mitigation. Previous versions had false. 11 | Rails.application.config.action_controller.forgery_protection_origin_check = true 12 | 13 | # Make Ruby 2.4 preserve the timezone of the receiver when calling `to_time`. 14 | # Previous versions had false. 15 | ActiveSupport.to_time_preserves_timezone = true 16 | 17 | # Require `belongs_to` associations by default. Previous versions had false. 18 | Rails.application.config.active_record.belongs_to_required_by_default = true 19 | 20 | # Configure SSL options to enable HSTS with subdomains. Previous versions had false. 21 | Rails.application.config.ssl_options = { hsts: { subdomains: true } } 22 | -------------------------------------------------------------------------------- /config/initializers/new_framework_defaults_6_1.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | # 3 | # This file contains migration options to ease your Rails 6.1 upgrade. 4 | # 5 | # Once upgraded flip defaults one by one to migrate to the new default. 6 | # 7 | # Read the Guide for Upgrading Ruby on Rails for more info on each option. 8 | 9 | # Support for inversing belongs_to -> has_many Active Record associations. 10 | # Rails.application.config.active_record.has_many_inversing = true 11 | 12 | # Track Active Storage variants in the database. 13 | # Rails.application.config.active_storage.track_variants = true 14 | 15 | # Apply random variation to the delay when retrying failed jobs. 16 | # Rails.application.config.active_job.retry_jitter = 0.15 17 | 18 | # Stop executing `after_enqueue`/`after_perform` callbacks if 19 | # `before_enqueue`/`before_perform` respectively halts with `throw :abort`. 20 | # Rails.application.config.active_job.skip_after_callbacks_if_terminated = true 21 | 22 | # Specify cookies SameSite protection level: either :none, :lax, or :strict. 23 | # 24 | # This change is not backwards compatible with earlier Rails versions. 25 | # It's best enabled when your entire app is migrated and stable on 6.1. 26 | # Rails.application.config.action_dispatch.cookies_same_site_protection = :lax 27 | 28 | # Generate CSRF tokens that are encoded in URL-safe Base64. 29 | # 30 | # This change is not backwards compatible with earlier Rails versions. 31 | # It's best enabled when your entire app is migrated and stable on 6.1. 32 | # Rails.application.config.action_controller.urlsafe_csrf_tokens = true 33 | 34 | # Specify whether `ActiveSupport::TimeZone.utc_to_local` returns a time with an 35 | # UTC offset or a UTC time. 36 | # ActiveSupport.utc_to_local_returns_utc_offset_times = true 37 | 38 | # Change the default HTTP status code to `308` when redirecting non-GET/HEAD 39 | # requests to HTTPS in `ActionDispatch::SSL` middleware. 40 | # Rails.application.config.action_dispatch.ssl_default_redirect_status = 308 41 | 42 | # Use new connection handling API. For most applications this won't have any 43 | # effect. For applications using multiple databases, this new API provides 44 | # support for granular connection swapping. 45 | # Rails.application.config.active_record.legacy_connection_handling = false 46 | 47 | # Make `form_with` generate non-remote forms by default. 48 | # Rails.application.config.action_view.form_with_generates_remote_forms = false 49 | 50 | # Set the default queue name for the analysis job to the queue adapter default. 51 | # Rails.application.config.active_storage.queues.analysis = nil 52 | 53 | # Set the default queue name for the purge job to the queue adapter default. 54 | # Rails.application.config.active_storage.queues.purge = nil 55 | 56 | # Set the default queue name for the incineration job to the queue adapter default. 57 | # Rails.application.config.action_mailbox.queues.incineration = nil 58 | 59 | # Set the default queue name for the routing job to the queue adapter default. 60 | # Rails.application.config.action_mailbox.queues.routing = nil 61 | 62 | # Set the default queue name for the mail deliver job to the queue adapter default. 63 | # Rails.application.config.action_mailer.deliver_later_queue_name = nil 64 | 65 | # Generate a `Link` header that gives a hint to modern browsers about 66 | # preloading assets when using `javascript_include_tag` and `stylesheet_link_tag`. 67 | # Rails.application.config.action_view.preload_links_header = true 68 | -------------------------------------------------------------------------------- /config/initializers/permissions_policy.rb: -------------------------------------------------------------------------------- 1 | # Define an application-wide HTTP permissions policy. For further 2 | # information see https://developers.google.com/web/updates/2018/06/feature-policy 3 | # 4 | # Rails.application.config.permissions_policy do |f| 5 | # f.camera :none 6 | # f.gyroscope :none 7 | # f.microphone :none 8 | # f.usb :none 9 | # f.fullscreen :self 10 | # f.payment :self, "https://secure.example.com" 11 | # end 12 | -------------------------------------------------------------------------------- /config/initializers/session_store.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | Rails.application.config.session_store :cookie_store, key: '_rails-ex_session' 4 | -------------------------------------------------------------------------------- /config/initializers/wrap_parameters.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # This file contains settings for ActionController::ParamsWrapper which 4 | # is enabled by default. 5 | 6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. 7 | ActiveSupport.on_load(:action_controller) do 8 | wrap_parameters format: [:json] 9 | end 10 | 11 | # To enable root element in JSON for ActiveRecord objects. 12 | # ActiveSupport.on_load(:active_record) do 13 | # self.include_root_in_json = true 14 | # end 15 | -------------------------------------------------------------------------------- /config/locales/en.yml: -------------------------------------------------------------------------------- 1 | # Files in the config/locales directory are used for internationalization 2 | # and are automatically loaded by Rails. If you want to use locales other 3 | # than English, add the necessary files in this directory. 4 | # 5 | # To use the locales, use `I18n.t`: 6 | # 7 | # I18n.t 'hello' 8 | # 9 | # In views, this is aliased to just `t`: 10 | # 11 | # <%= t('hello') %> 12 | # 13 | # To use a different locale, set it with `I18n.locale`: 14 | # 15 | # I18n.locale = :es 16 | # 17 | # This would use the information in config/locales/es.yml. 18 | # 19 | # The following keys must be escaped otherwise they will not be retrieved by 20 | # the default I18n backend: 21 | # 22 | # true, false, on, off, yes, no 23 | # 24 | # Instead, surround them with single quotes. 25 | # 26 | # en: 27 | # 'true': 'foo' 28 | # 29 | # To learn more, please read the Rails Internationalization guide 30 | # available at https://guides.rubyonrails.org/i18n.html. 31 | 32 | en: 33 | hello: "Hello world" 34 | -------------------------------------------------------------------------------- /config/puma.rb: -------------------------------------------------------------------------------- 1 | # Puma can serve each request in a thread from an internal thread pool. 2 | # The `threads` method setting takes two numbers: a minimum and maximum. 3 | # Any libraries that use thread pools should be configured to match 4 | # the maximum value specified for Puma. Default is set to 5 threads for minimum 5 | # and maximum; this matches the default thread size of Active Record. 6 | # 7 | max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 } 8 | min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count } 9 | threads min_threads_count, max_threads_count 10 | 11 | # Specifies the `worker_timeout` threshold that Puma will use to wait before 12 | # terminating a worker in development environments. 13 | # 14 | worker_timeout 3600 if ENV.fetch("RAILS_ENV", "development") == "development" 15 | 16 | # Specifies the `port` that Puma will listen on to receive requests; default is 3000. 17 | # 18 | port ENV.fetch("PORT") { 3000 } 19 | 20 | # Specifies the `environment` that Puma will run in. 21 | # 22 | environment ENV.fetch("RAILS_ENV") { "development" } 23 | 24 | # Specifies the `pidfile` that Puma will use. 25 | # pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" } 26 | 27 | # Specifies the number of `workers` to boot in clustered mode. 28 | # Workers are forked web server processes. If using threads and workers together 29 | # the concurrency of the application would be max `threads` * `workers`. 30 | # Workers do not work on JRuby or Windows (both of which do not support 31 | # processes). 32 | # 33 | # workers ENV.fetch("WEB_CONCURRENCY") { 2 } 34 | 35 | # Use the `preload_app!` method when specifying a `workers` number. 36 | # This directive tells Puma to first boot the application and load code 37 | # before forking the application. This takes advantage of Copy On Write 38 | # process behavior so workers use less memory. 39 | # 40 | # preload_app! 41 | 42 | # Allow puma to be restarted by `rails restart` command. 43 | plugin :tmp_restart 44 | -------------------------------------------------------------------------------- /config/routes.rb: -------------------------------------------------------------------------------- 1 | Rails.application.routes.draw do 2 | get 'welcome/index' 3 | root 'welcome#index' 4 | resources :articles do 5 | resources :comments 6 | end 7 | # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html 8 | end 9 | -------------------------------------------------------------------------------- /config/secrets.yml: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Your secret key is used for verifying the integrity of signed cookies. 4 | # If you change this key, all old signed cookies will become invalid! 5 | 6 | # Make sure the secret is at least 30 characters and all random, 7 | # no regular words or you'll be exposed to dictionary attacks. 8 | # You can use `rails secret` to generate a secure secret key. 9 | 10 | # Make sure the secrets in this file are kept private 11 | # if you're sharing your code publicly. 12 | 13 | # Shared secrets are available across all environments. 14 | 15 | # shared: 16 | # api_key: a1B2c3D4e5F6 17 | 18 | # Environmental secrets are only available for that specific environment. 19 | 20 | development: 21 | secret_key_base: <%= ENV["SECRET_KEY_BASE"] || "development-key" %> 22 | 23 | test: 24 | secret_key_base: <%= ENV["SECRET_KEY_BASE"] || "test-key" %> 25 | 26 | # Do not keep production secrets in the unencrypted secrets file. 27 | # Instead, either read values from the environment. 28 | # Or, use `bin/rails secrets:setup` to configure encrypted secrets 29 | # and move the `production:` environment over there. 30 | 31 | production: 32 | secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> 33 | -------------------------------------------------------------------------------- /config/spring.rb: -------------------------------------------------------------------------------- 1 | Spring.watch( 2 | ".ruby-version", 3 | ".rbenv-vars", 4 | "tmp/restart.txt", 5 | "tmp/caching-dev.txt" 6 | ) 7 | -------------------------------------------------------------------------------- /config/storage.yml: -------------------------------------------------------------------------------- 1 | test: 2 | service: Disk 3 | root: <%= Rails.root.join("tmp/storage") %> 4 | 5 | local: 6 | service: Disk 7 | root: <%= Rails.root.join("storage") %> 8 | 9 | # Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) 10 | # amazon: 11 | # service: S3 12 | # access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> 13 | # secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> 14 | # region: us-east-1 15 | # bucket: your_own_bucket 16 | 17 | # Remember not to checkin your GCS keyfile to a repository 18 | # google: 19 | # service: GCS 20 | # project: your_project 21 | # credentials: <%= Rails.root.join("path/to/gcs.keyfile") %> 22 | # bucket: your_own_bucket 23 | 24 | # Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key) 25 | # microsoft: 26 | # service: AzureStorage 27 | # storage_account_name: your_account_name 28 | # storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %> 29 | # container: your_container_name 30 | 31 | # mirror: 32 | # service: Mirror 33 | # primary: local 34 | # mirrors: [ amazon, google, microsoft ] 35 | -------------------------------------------------------------------------------- /db/migrate/20161103112943_create_articles.rb: -------------------------------------------------------------------------------- 1 | class CreateArticles < ActiveRecord::Migration[5.0] 2 | def change 3 | create_table :articles do |t| 4 | t.string :title 5 | t.text :body 6 | 7 | t.timestamps 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20161103113002_create_comments.rb: -------------------------------------------------------------------------------- 1 | class CreateComments < ActiveRecord::Migration[5.0] 2 | def change 3 | create_table :comments do |t| 4 | t.string :commenter 5 | t.text :body 6 | t.references :article, index: true, foreign_key: true 7 | t.timestamps 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/schema.rb: -------------------------------------------------------------------------------- 1 | # This file is auto-generated from the current state of the database. Instead 2 | # of editing this file, please use the migrations feature of Active Record to 3 | # incrementally modify your database, and then regenerate this schema definition. 4 | # 5 | # Note that this schema.rb definition is the authoritative source for your 6 | # database schema. If you need to create the application database on another 7 | # system, you should be using db:schema:load, not running all the migrations 8 | # from scratch. The latter is a flawed and unsustainable approach (the more migrations 9 | # you'll amass, the slower it'll run and the greater likelihood for issues). 10 | # 11 | # It's strongly recommended that you check this file into your version control system. 12 | 13 | ActiveRecord::Schema.define(version: 20161103113002) do 14 | 15 | create_table "articles", force: :cascade do |t| 16 | t.string "title" 17 | t.text "body" 18 | t.datetime "created_at", null: false 19 | t.datetime "updated_at", null: false 20 | end 21 | 22 | create_table "comments", force: :cascade do |t| 23 | t.string "commenter" 24 | t.text "body" 25 | t.integer "article_id" 26 | t.datetime "created_at", null: false 27 | t.datetime "updated_at", null: false 28 | t.index ["article_id"], name: "index_comments_on_article_id" 29 | end 30 | 31 | end 32 | -------------------------------------------------------------------------------- /db/seeds.rb: -------------------------------------------------------------------------------- 1 | # This file should contain all the record creation needed to seed the database with its default values. 2 | # The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup). 3 | # 4 | # Examples: 5 | # 6 | # movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }]) 7 | # Character.create(name: 'Luke', movie: movies.first) 8 | -------------------------------------------------------------------------------- /lib/assets/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sclorg/rails-ex/482ef27972d3f594b1e3a1481c1113075238496d/lib/assets/.keep -------------------------------------------------------------------------------- /lib/tasks/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sclorg/rails-ex/482ef27972d3f594b1e3a1481c1113075238496d/lib/tasks/.keep -------------------------------------------------------------------------------- /migrate-database.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | echo "Executing bundle exec 'rake db:migrate' ..." 5 | RAILS_ENV=production bundle exec rake db:migrate 6 | -------------------------------------------------------------------------------- /openshift/templates/rails-postgresql-persistent.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "Template", 3 | "apiVersion": "template.openshift.io/v1", 4 | "metadata": { 5 | "name": "rails-pgsql-persistent", 6 | "annotations": { 7 | "openshift.io/display-name": "Rails + PostgreSQL (Persistent)", 8 | "description": "An example Rails application with a PostgreSQL database. For more information about using this template, including OpenShift considerations, see https://github.com/sclorg/rails-ex/blob/master/README.md.", 9 | "tags": "quickstart,ruby,rails", 10 | "iconClass": "icon-ruby", 11 | "template.openshift.io/long-description": "This template defines resources needed to develop a Rails application, including a build configuration, application deployment configuration, and database deployment configuration.", 12 | "template.openshift.io/provider-display-name": "Red Hat, Inc.", 13 | "template.openshift.io/documentation-url": "https://github.com/sclorg/rails-ex", 14 | "template.openshift.io/support-url": "https://access.redhat.com" 15 | } 16 | }, 17 | "message": "The following service(s) have been created in your project: ${NAME}, ${DATABASE_SERVICE_NAME}.\n\nFor more information about using this template, including OpenShift considerations, see https://github.com/sclorg/rails-ex/blob/master/README.md.", 18 | "labels": { 19 | "template": "rails-pgsql-persistent", 20 | "app": "rails-pgsql-persistent" 21 | }, 22 | "objects": [ 23 | { 24 | "kind": "Secret", 25 | "apiVersion": "v1", 26 | "metadata": { 27 | "name": "${NAME}", 28 | "annotations": { 29 | "template.openshift.io/expose-username": "{.data['application-user']}", 30 | "template.openshift.io/expose-password": "{.data['application-password']}" 31 | } 32 | }, 33 | "stringData" : { 34 | "database-user" : "${DATABASE_USER}", 35 | "database-password" : "${DATABASE_PASSWORD}", 36 | "application-user" : "${APPLICATION_USER}", 37 | "application-password" : "${APPLICATION_PASSWORD}", 38 | "keybase" : "${SECRET_KEY_BASE}" 39 | } 40 | }, 41 | { 42 | "kind": "Service", 43 | "apiVersion": "v1", 44 | "metadata": { 45 | "name": "${NAME}", 46 | "annotations": { 47 | "description": "Exposes and load balances the application pods", 48 | "service.alpha.openshift.io/dependencies": "[{\"name\": \"${DATABASE_SERVICE_NAME}\", \"kind\": \"Service\"}]" 49 | } 50 | }, 51 | "spec": { 52 | "ports": [ 53 | { 54 | "name": "web", 55 | "port": 8080, 56 | "targetPort": 8080 57 | } 58 | ], 59 | "selector": { 60 | "name": "${NAME}" 61 | } 62 | } 63 | }, 64 | { 65 | "kind": "Route", 66 | "apiVersion": "route.openshift.io/v1", 67 | "metadata": { 68 | "name": "${NAME}", 69 | "annotations": { 70 | "template.openshift.io/expose-uri": "http://{.spec.host}{.spec.path}" 71 | } 72 | }, 73 | "spec": { 74 | "host": "${APPLICATION_DOMAIN}", 75 | "to": { 76 | "kind": "Service", 77 | "name": "${NAME}" 78 | } 79 | } 80 | }, 81 | { 82 | "kind": "ImageStream", 83 | "apiVersion": "image.openshift.io/v1", 84 | "metadata": { 85 | "name": "${NAME}", 86 | "annotations": { 87 | "description": "Keeps track of changes in the application image" 88 | } 89 | } 90 | }, 91 | { 92 | "kind": "BuildConfig", 93 | "apiVersion": "build.openshift.io/v1", 94 | "metadata": { 95 | "name": "${NAME}", 96 | "annotations": { 97 | "description": "Defines how to build the application", 98 | "template.alpha.openshift.io/wait-for-ready": "true" 99 | } 100 | }, 101 | "spec": { 102 | "source": { 103 | "type": "Git", 104 | "git": { 105 | "uri": "${SOURCE_REPOSITORY_URL}", 106 | "ref": "${SOURCE_REPOSITORY_REF}" 107 | }, 108 | "contextDir": "${CONTEXT_DIR}" 109 | }, 110 | "strategy": { 111 | "type": "Source", 112 | "sourceStrategy": { 113 | "from": { 114 | "kind": "ImageStreamTag", 115 | "namespace": "${NAMESPACE}", 116 | "name": "ruby:${RUBY_VERSION}" 117 | }, 118 | "env": [ 119 | { 120 | "name": "RUBYGEM_MIRROR", 121 | "value": "${RUBYGEM_MIRROR}" 122 | } 123 | ] 124 | } 125 | }, 126 | "output": { 127 | "to": { 128 | "kind": "ImageStreamTag", 129 | "name": "${NAME}:latest" 130 | } 131 | }, 132 | "triggers": [ 133 | { 134 | "type": "ImageChange" 135 | }, 136 | { 137 | "type": "ConfigChange" 138 | }, 139 | { 140 | "type": "GitHub", 141 | "github": { 142 | "secret": "${GITHUB_WEBHOOK_SECRET}" 143 | } 144 | } 145 | ] 146 | } 147 | }, 148 | { 149 | "kind": "Deployment", 150 | "apiVersion": "apps/v1", 151 | "metadata": { 152 | "name": "${NAME}", 153 | "annotations": { 154 | "description": "Defines how to deploy the application server", 155 | "template.alpha.openshift.io/wait-for-ready": "true", 156 | "image.openshift.io/triggers": "[{\"from\":{\"kind\":\"ImageStreamTag\",\"name\":\"${NAME}:latest\"},\"fieldPath\": \"spec.template.spec.containers[0].image\"},{\"from\":{\"kind\":\"ImageStreamTag\",\"name\":\"${NAME}:latest\"},\"fieldPath\": \"spec.template.spec.initContainers[0].image\"}]" 157 | } 158 | }, 159 | "spec": { 160 | "strategy": { 161 | "type": "Recreate" 162 | }, 163 | "replicas": 1, 164 | "selector": { 165 | "matchLabels": { 166 | "name": "${NAME}" 167 | } 168 | }, 169 | "template": { 170 | "metadata": { 171 | "name": "${NAME}", 172 | "labels": { 173 | "name": "${NAME}" 174 | } 175 | }, 176 | "spec": { 177 | "initContainers": [ 178 | { 179 | "name": "ruby-init-container", 180 | "image": " ", 181 | "command": [ 182 | "./migrate-database.sh" 183 | ], 184 | "env": [ 185 | { 186 | "name": "DATABASE_SERVICE_NAME", 187 | "value": "${DATABASE_SERVICE_NAME}" 188 | }, 189 | { 190 | "name": "POSTGRESQL_USER", 191 | "valueFrom": { 192 | "secretKeyRef" : { 193 | "name" : "${NAME}", 194 | "key" : "database-user" 195 | } 196 | } 197 | }, 198 | { 199 | "name": "POSTGRESQL_PASSWORD", 200 | "valueFrom": { 201 | "secretKeyRef" : { 202 | "name" : "${NAME}", 203 | "key" : "database-password" 204 | } 205 | } 206 | }, 207 | { 208 | "name": "SECRET_KEY_BASE", 209 | "valueFrom": { 210 | "secretKeyRef" : { 211 | "name" : "${NAME}", 212 | "key" : "keybase" 213 | } 214 | } 215 | }, 216 | { 217 | "name": "POSTGRESQL_DATABASE", 218 | "value": "${DATABASE_NAME}" 219 | }, 220 | { 221 | "name": "POSTGRESQL_MAX_CONNECTIONS", 222 | "value": "${POSTGRESQL_MAX_CONNECTIONS}" 223 | }, 224 | { 225 | "name": "POSTGRESQL_SHARED_BUFFERS", 226 | "value": "${POSTGRESQL_SHARED_BUFFERS}" 227 | }, 228 | { 229 | "name": "APPLICATION_DOMAIN", 230 | "value": "${APPLICATION_DOMAIN}" 231 | }, 232 | { 233 | "name": "APPLICATION_USER", 234 | "valueFrom": { 235 | "secretKeyRef" : { 236 | "name" : "${NAME}", 237 | "key" : "application-user" 238 | } 239 | } 240 | }, 241 | { 242 | "name": "APPLICATION_PASSWORD", 243 | "valueFrom": { 244 | "secretKeyRef" : { 245 | "name" : "${NAME}", 246 | "key" : "application-password" 247 | } 248 | } 249 | }, 250 | { 251 | "name": "RAILS_ENV", 252 | "value": "${RAILS_ENV}" 253 | } 254 | ] 255 | } 256 | ], 257 | "containers": [ 258 | { 259 | "name": "${NAME}", 260 | "image": " ", 261 | "ports": [ 262 | { 263 | "containerPort": 8080 264 | } 265 | ], 266 | "readinessProbe": { 267 | "timeoutSeconds": 3, 268 | "initialDelaySeconds": 5, 269 | "httpGet": { 270 | "path": "/articles", 271 | "port": 8080 272 | } 273 | }, 274 | "livenessProbe": { 275 | "timeoutSeconds": 3, 276 | "initialDelaySeconds": 10, 277 | "httpGet": { 278 | "path": "/articles", 279 | "port": 8080 280 | } 281 | }, 282 | "env": [ 283 | { 284 | "name": "DATABASE_SERVICE_NAME", 285 | "value": "${DATABASE_SERVICE_NAME}" 286 | }, 287 | { 288 | "name": "POSTGRESQL_USER", 289 | "valueFrom": { 290 | "secretKeyRef" : { 291 | "name" : "${NAME}", 292 | "key" : "database-user" 293 | } 294 | } 295 | }, 296 | { 297 | "name": "POSTGRESQL_PASSWORD", 298 | "valueFrom": { 299 | "secretKeyRef" : { 300 | "name" : "${NAME}", 301 | "key" : "database-password" 302 | } 303 | } 304 | }, 305 | { 306 | "name": "SECRET_KEY_BASE", 307 | "valueFrom": { 308 | "secretKeyRef" : { 309 | "name" : "${NAME}", 310 | "key" : "keybase" 311 | } 312 | } 313 | }, 314 | { 315 | "name": "POSTGRESQL_DATABASE", 316 | "value": "${DATABASE_NAME}" 317 | }, 318 | { 319 | "name": "POSTGRESQL_MAX_CONNECTIONS", 320 | "value": "${POSTGRESQL_MAX_CONNECTIONS}" 321 | }, 322 | { 323 | "name": "POSTGRESQL_SHARED_BUFFERS", 324 | "value": "${POSTGRESQL_SHARED_BUFFERS}" 325 | }, 326 | { 327 | "name": "APPLICATION_DOMAIN", 328 | "value": "${APPLICATION_DOMAIN}" 329 | }, 330 | { 331 | "name": "APPLICATION_USER", 332 | "valueFrom": { 333 | "secretKeyRef" : { 334 | "name" : "${NAME}", 335 | "key" : "application-user" 336 | } 337 | } 338 | }, 339 | { 340 | "name": "APPLICATION_PASSWORD", 341 | "valueFrom": { 342 | "secretKeyRef" : { 343 | "name" : "${NAME}", 344 | "key" : "application-password" 345 | } 346 | } 347 | }, 348 | { 349 | "name": "RAILS_ENV", 350 | "value": "${RAILS_ENV}" 351 | } 352 | ], 353 | "resources": { 354 | "limits": { 355 | "memory": "${MEMORY_LIMIT}" 356 | } 357 | } 358 | } 359 | ] 360 | } 361 | } 362 | } 363 | }, 364 | { 365 | "kind": "PersistentVolumeClaim", 366 | "apiVersion": "v1", 367 | "metadata": { 368 | "name": "${DATABASE_SERVICE_NAME}" 369 | }, 370 | "spec": { 371 | "accessModes": [ 372 | "ReadWriteOnce" 373 | ], 374 | "resources": { 375 | "requests": { 376 | "storage": "${VOLUME_CAPACITY}" 377 | } 378 | } 379 | } 380 | }, 381 | { 382 | "kind": "Service", 383 | "apiVersion": "v1", 384 | "metadata": { 385 | "name": "${DATABASE_SERVICE_NAME}", 386 | "annotations": { 387 | "description": "Exposes the database server" 388 | } 389 | }, 390 | "spec": { 391 | "ports": [ 392 | { 393 | "name": "postgresql", 394 | "port": 5432, 395 | "targetPort": 5432 396 | } 397 | ], 398 | "selector": { 399 | "name": "${DATABASE_SERVICE_NAME}" 400 | } 401 | } 402 | }, 403 | { 404 | "kind": "Deployment", 405 | "apiVersion": "apps/v1", 406 | "metadata": { 407 | "name": "${DATABASE_SERVICE_NAME}", 408 | "annotations": { 409 | "description": "Defines how to deploy the database", 410 | "template.alpha.openshift.io/wait-for-ready": "true", 411 | "image.openshift.io/triggers": "[{\"from\":{\"kind\":\"ImageStreamTag\",\"name\":\"postgresql:${POSTGRESQL_VERSION}\", \"namespace\": \"${NAMESPACE}\"},\"fieldPath\": \"spec.template.spec.containers[0].image\"}]" 412 | } 413 | }, 414 | "spec": { 415 | "strategy": { 416 | "type": "Recreate" 417 | }, 418 | "replicas": 1, 419 | "selector": { 420 | "matchLabels": { 421 | "name": "${DATABASE_SERVICE_NAME}" 422 | } 423 | }, 424 | "template": { 425 | "metadata": { 426 | "name": "${DATABASE_SERVICE_NAME}", 427 | "labels": { 428 | "name": "${DATABASE_SERVICE_NAME}" 429 | } 430 | }, 431 | "spec": { 432 | "volumes": [ 433 | { 434 | "name": "${DATABASE_SERVICE_NAME}-data", 435 | "persistentVolumeClaim": { 436 | "claimName": "${DATABASE_SERVICE_NAME}" 437 | } 438 | } 439 | ], 440 | "containers": [ 441 | { 442 | "name": "postgresql", 443 | "image": " ", 444 | "ports": [ 445 | { 446 | "containerPort": 5432 447 | } 448 | ], 449 | "readinessProbe": { 450 | "timeoutSeconds": 1, 451 | "initialDelaySeconds": 5, 452 | "exec": { 453 | "command": [ "/usr/libexec/check-container" ] 454 | } 455 | }, 456 | "livenessProbe": { 457 | "timeoutSeconds": 10, 458 | "initialDelaySeconds": 120, 459 | "exec": { 460 | "command": [ "/usr/libexec/check-container", "--live" ] 461 | } 462 | }, 463 | "volumeMounts": [ 464 | { 465 | "name": "${DATABASE_SERVICE_NAME}-data", 466 | "mountPath": "/var/lib/pgsql/data" 467 | } 468 | ], 469 | "env": [ 470 | { 471 | "name": "POSTGRESQL_USER", 472 | "valueFrom": { 473 | "secretKeyRef" : { 474 | "name" : "${NAME}", 475 | "key" : "database-user" 476 | } 477 | } 478 | }, 479 | { 480 | "name": "POSTGRESQL_PASSWORD", 481 | "valueFrom": { 482 | "secretKeyRef" : { 483 | "name" : "${NAME}", 484 | "key" : "database-password" 485 | } 486 | } 487 | }, 488 | { 489 | "name": "POSTGRESQL_DATABASE", 490 | "value": "${DATABASE_NAME}" 491 | }, 492 | { 493 | "name": "POSTGRESQL_MAX_CONNECTIONS", 494 | "value": "${POSTGRESQL_MAX_CONNECTIONS}" 495 | }, 496 | { 497 | "name": "POSTGRESQL_SHARED_BUFFERS", 498 | "value": "${POSTGRESQL_SHARED_BUFFERS}" 499 | } 500 | ], 501 | "resources": { 502 | "limits": { 503 | "memory": "${MEMORY_POSTGRESQL_LIMIT}" 504 | } 505 | } 506 | } 507 | ] 508 | } 509 | } 510 | } 511 | } 512 | ], 513 | "parameters": [ 514 | { 515 | "name": "NAME", 516 | "displayName": "Name", 517 | "description": "The name assigned to all of the frontend objects defined in this template.", 518 | "required": true, 519 | "value": "rails-pgsql-persistent" 520 | }, 521 | { 522 | "name": "NAMESPACE", 523 | "displayName": "Namespace", 524 | "required": true, 525 | "description": "The OpenShift Namespace where the ImageStream resides.", 526 | "value": "openshift" 527 | }, 528 | { 529 | "name": "RUBY_VERSION", 530 | "displayName": "Ruby Version", 531 | "description": "Version of Ruby image to be used (3.1-ubi8 by default).", 532 | "required": true, 533 | "value": "3.1-ubi8" 534 | }, 535 | { 536 | "name": "POSTGRESQL_VERSION", 537 | "displayName": "Postgresql Version", 538 | "description": "Version of Postgresql image to be used (12-el8 by default).", 539 | "required": true, 540 | "value": "12-el8" 541 | }, 542 | { 543 | "name": "MEMORY_LIMIT", 544 | "displayName": "Memory Limit", 545 | "required": true, 546 | "description": "Maximum amount of memory the Rails container can use.", 547 | "value": "512Mi" 548 | }, 549 | { 550 | "name": "MEMORY_POSTGRESQL_LIMIT", 551 | "displayName": "Memory Limit (PostgreSQL)", 552 | "required": true, 553 | "description": "Maximum amount of memory the PostgreSQL container can use.", 554 | "value": "512Mi" 555 | }, 556 | { 557 | "name": "VOLUME_CAPACITY", 558 | "displayName": "Volume Capacity", 559 | "description": "Volume space available for data, e.g. 512Mi, 2Gi", 560 | "value": "1Gi", 561 | "required": true 562 | }, 563 | { 564 | "name": "SOURCE_REPOSITORY_URL", 565 | "displayName": "Git Repository URL", 566 | "required": true, 567 | "description": "The URL of the repository with your application source code.", 568 | "value": "https://github.com/sclorg/rails-ex.git" 569 | }, 570 | { 571 | "name": "SOURCE_REPOSITORY_REF", 572 | "displayName": "Git Reference", 573 | "description": "Set this to a branch name, tag or other ref of your repository if you are not using the default branch." 574 | }, 575 | { 576 | "name": "CONTEXT_DIR", 577 | "displayName": "Context Directory", 578 | "description": "Set this to the relative path to your project if it is not in the root of your repository." 579 | }, 580 | { 581 | "name": "APPLICATION_DOMAIN", 582 | "displayName": "Application Hostname", 583 | "description": "The exposed hostname that will route to the Rails service, if left blank a value will be defaulted.", 584 | "value": "" 585 | }, 586 | { 587 | "name": "GITHUB_WEBHOOK_SECRET", 588 | "displayName": "GitHub Webhook Secret", 589 | "description": "Github trigger secret. A difficult to guess string encoded as part of the webhook URL. Not encrypted.", 590 | "generate": "expression", 591 | "from": "[a-zA-Z0-9]{40}" 592 | }, 593 | { 594 | "name": "SECRET_KEY_BASE", 595 | "displayName": "Secret Key", 596 | "description": "Your secret key for verifying the integrity of signed cookies.", 597 | "generate": "expression", 598 | "from": "[a-z0-9]{127}" 599 | }, 600 | { 601 | "name": "APPLICATION_USER", 602 | "displayName": "Application Username", 603 | "required": true, 604 | "description": "The application user that is used within the sample application to authorize access on pages.", 605 | "value": "openshift" 606 | }, 607 | { 608 | "name": "APPLICATION_PASSWORD", 609 | "displayName": "Application Password", 610 | "required": true, 611 | "description": "The application password that is used within the sample application to authorize access on pages.", 612 | "value": "secret" 613 | }, 614 | { 615 | "name": "RAILS_ENV", 616 | "displayName": "Rails Environment", 617 | "required": true, 618 | "description": "Environment under which the sample application will run. Could be set to production, development or test.", 619 | "value": "production" 620 | }, 621 | { 622 | "name": "DATABASE_SERVICE_NAME", 623 | "required": true, 624 | "displayName": "Database Service Name", 625 | "value": "postgresql" 626 | }, 627 | { 628 | "name": "DATABASE_USER", 629 | "displayName": "Database Username", 630 | "generate": "expression", 631 | "from": "user[A-Z0-9]{3}" 632 | }, 633 | { 634 | "name": "DATABASE_PASSWORD", 635 | "displayName": "Database Password", 636 | "generate": "expression", 637 | "from": "[a-zA-Z0-9]{8}" 638 | }, 639 | { 640 | "name": "DATABASE_NAME", 641 | "required": true, 642 | "displayName": "Database Name", 643 | "value": "root" 644 | }, 645 | { 646 | "name": "POSTGRESQL_MAX_CONNECTIONS", 647 | "displayName": "Maximum Database Connections", 648 | "value": "100" 649 | }, 650 | { 651 | "name": "POSTGRESQL_SHARED_BUFFERS", 652 | "displayName": "Shared Buffer Amount", 653 | "value": "12MB" 654 | }, 655 | { 656 | "name": "RUBYGEM_MIRROR", 657 | "displayName": "Custom RubyGems Mirror URL", 658 | "description": "The custom RubyGems mirror URL", 659 | "value": "" 660 | } 661 | ] 662 | } 663 | -------------------------------------------------------------------------------- /openshift/templates/rails-postgresql.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "Template", 3 | "apiVersion": "template.openshift.io/v1", 4 | "metadata": { 5 | "name": "rails-postgresql-example", 6 | "annotations": { 7 | "openshift.io/display-name": "Rails + PostgreSQL (Ephemeral)", 8 | "description": "An example Rails application with a PostgreSQL database. For more information about using this template, including OpenShift considerations, see https://github.com/sclorg/rails-ex/blob/master/README.md.\n\nWARNING: Any data stored will be lost upon pod destruction. Only use this template for testing.", 9 | "tags": "quickstart,ruby,rails", 10 | "iconClass": "icon-ruby", 11 | "openshift.io/long-description": "This template defines resources needed to develop a Rails application, including a build configuration, application deployment configuration, and database deployment configuration. The database is stored in non-persistent storage, so this configuration should be used for experimental purposes only.", 12 | "openshift.io/provider-display-name": "Red Hat, Inc.", 13 | "openshift.io/documentation-url": "https://github.com/sclorg/rails-ex", 14 | "openshift.io/support-url": "https://access.redhat.com", 15 | "template.openshift.io/bindable": "false" 16 | } 17 | }, 18 | "message": "The following service(s) have been created in your project: ${NAME}, ${DATABASE_SERVICE_NAME}.\n\nFor more information about using this template, including OpenShift considerations, see https://github.com/sclorg/rails-ex/blob/master/README.md.", 19 | "labels": { 20 | "template": "rails-postgresql-example", 21 | "app": "rails-postgresql-example" 22 | }, 23 | "objects": [ 24 | { 25 | "kind": "Secret", 26 | "apiVersion": "v1", 27 | "metadata": { 28 | "name": "${NAME}" 29 | }, 30 | "stringData" : { 31 | "database-user" : "${DATABASE_USER}", 32 | "database-password" : "${DATABASE_PASSWORD}", 33 | "application-user" : "${APPLICATION_USER}", 34 | "application-password" : "${APPLICATION_PASSWORD}", 35 | "keybase" : "${SECRET_KEY_BASE}" 36 | } 37 | }, 38 | { 39 | "kind": "Service", 40 | "apiVersion": "v1", 41 | "metadata": { 42 | "name": "${NAME}", 43 | "annotations": { 44 | "description": "Exposes and load balances the application pods", 45 | "service.alpha.openshift.io/dependencies": "[{\"name\": \"${DATABASE_SERVICE_NAME}\", \"kind\": \"Service\"}]" 46 | } 47 | }, 48 | "spec": { 49 | "ports": [ 50 | { 51 | "name": "web", 52 | "port": 8080, 53 | "targetPort": 8080 54 | } 55 | ], 56 | "selector": { 57 | "name": "${NAME}" 58 | } 59 | } 60 | }, 61 | { 62 | "kind": "Route", 63 | "apiVersion": "route.openshift.io/v1", 64 | "metadata": { 65 | "name": "${NAME}" 66 | }, 67 | "spec": { 68 | "host": "${APPLICATION_DOMAIN}", 69 | "to": { 70 | "kind": "Service", 71 | "name": "${NAME}" 72 | } 73 | } 74 | }, 75 | { 76 | "kind": "ImageStream", 77 | "apiVersion": "image.openshift.io/v1", 78 | "metadata": { 79 | "name": "${NAME}", 80 | "annotations": { 81 | "description": "Keeps track of changes in the application image" 82 | } 83 | } 84 | }, 85 | { 86 | "kind": "BuildConfig", 87 | "apiVersion": "build.openshift.io/v1", 88 | "metadata": { 89 | "name": "${NAME}", 90 | "annotations": { 91 | "description": "Defines how to build the application", 92 | "template.alpha.openshift.io/wait-for-ready": "true" 93 | } 94 | }, 95 | "spec": { 96 | "source": { 97 | "type": "Git", 98 | "git": { 99 | "uri": "${SOURCE_REPOSITORY_URL}", 100 | "ref": "${SOURCE_REPOSITORY_REF}" 101 | }, 102 | "contextDir": "${CONTEXT_DIR}" 103 | }, 104 | "strategy": { 105 | "type": "Source", 106 | "sourceStrategy": { 107 | "from": { 108 | "kind": "ImageStreamTag", 109 | "namespace": "${NAMESPACE}", 110 | "name": "ruby:${RUBY_VERSION}" 111 | }, 112 | "env": [ 113 | { 114 | "name": "RUBYGEM_MIRROR", 115 | "value": "${RUBYGEM_MIRROR}" 116 | } 117 | ] 118 | } 119 | }, 120 | "output": { 121 | "to": { 122 | "kind": "ImageStreamTag", 123 | "name": "${NAME}:latest" 124 | } 125 | }, 126 | "triggers": [ 127 | { 128 | "type": "ImageChange" 129 | }, 130 | { 131 | "type": "ConfigChange" 132 | }, 133 | { 134 | "type": "GitHub", 135 | "github": { 136 | "secret": "${GITHUB_WEBHOOK_SECRET}" 137 | } 138 | } 139 | ] 140 | } 141 | }, 142 | { 143 | "kind": "Deployment", 144 | "apiVersion": "apps/v1", 145 | "metadata": { 146 | "name": "${NAME}", 147 | "annotations": { 148 | "description": "Defines how to deploy the application server", 149 | "template.alpha.openshift.io/wait-for-ready": "true", 150 | "image.openshift.io/triggers": "[{\"from\":{\"kind\":\"ImageStreamTag\",\"name\":\"${NAME}:latest\"},\"fieldPath\": \"spec.template.spec.containers[0].image\"},{\"from\":{\"kind\":\"ImageStreamTag\",\"name\":\"${NAME}:latest\"},\"fieldPath\": \"spec.template.spec.initContainers[0].image\"}]" 151 | } 152 | }, 153 | "spec": { 154 | "strategy": { 155 | "type": "Recreate" 156 | }, 157 | "replicas": 1, 158 | "selector": { 159 | "matchLabels": { 160 | "name": "${NAME}" 161 | } 162 | }, 163 | "template": { 164 | "metadata": { 165 | "name": "${NAME}", 166 | "labels": { 167 | "name": "${NAME}" 168 | } 169 | }, 170 | "spec": { 171 | "initContainers": [ 172 | { 173 | "name": "ruby-init-container", 174 | "image": " ", 175 | "command": [ 176 | "./migrate-database.sh" 177 | ], 178 | "env": [ 179 | { 180 | "name": "DATABASE_SERVICE_NAME", 181 | "value": "${DATABASE_SERVICE_NAME}" 182 | }, 183 | { 184 | "name": "POSTGRESQL_USER", 185 | "valueFrom": { 186 | "secretKeyRef": { 187 | "name": "${NAME}", 188 | "key": "database-user" 189 | } 190 | } 191 | }, 192 | { 193 | "name": "POSTGRESQL_PASSWORD", 194 | "valueFrom": { 195 | "secretKeyRef": { 196 | "name": "${NAME}", 197 | "key": "database-password" 198 | } 199 | } 200 | }, 201 | { 202 | "name": "SECRET_KEY_BASE", 203 | "valueFrom": { 204 | "secretKeyRef": { 205 | "name": "${NAME}", 206 | "key": "keybase" 207 | } 208 | } 209 | }, 210 | { 211 | "name": "POSTGRESQL_DATABASE", 212 | "value": "${DATABASE_NAME}" 213 | }, 214 | { 215 | "name": "POSTGRESQL_MAX_CONNECTIONS", 216 | "value": "${POSTGRESQL_MAX_CONNECTIONS}" 217 | }, 218 | { 219 | "name": "POSTGRESQL_SHARED_BUFFERS", 220 | "value": "${POSTGRESQL_SHARED_BUFFERS}" 221 | }, 222 | { 223 | "name": "APPLICATION_DOMAIN", 224 | "value": "${APPLICATION_DOMAIN}" 225 | }, 226 | { 227 | "name": "APPLICATION_USER", 228 | "valueFrom": { 229 | "secretKeyRef": { 230 | "name": "${NAME}", 231 | "key": "application-user" 232 | } 233 | } 234 | }, 235 | { 236 | "name": "APPLICATION_PASSWORD", 237 | "valueFrom": { 238 | "secretKeyRef": { 239 | "name": "${NAME}", 240 | "key": "application-password" 241 | } 242 | } 243 | }, 244 | { 245 | "name": "RAILS_ENV", 246 | "value": "${RAILS_ENV}" 247 | } 248 | ] 249 | } 250 | ], 251 | "containers": [ 252 | { 253 | "name": "${NAME}", 254 | "image": " ", 255 | "ports": [ 256 | { 257 | "containerPort": 8080 258 | } 259 | ], 260 | "readinessProbe": { 261 | "timeoutSeconds": 3, 262 | "initialDelaySeconds": 5, 263 | "httpGet": { 264 | "path": "/articles", 265 | "port": 8080 266 | } 267 | }, 268 | "livenessProbe": { 269 | "timeoutSeconds": 3, 270 | "initialDelaySeconds": 10, 271 | "httpGet": { 272 | "path": "/articles", 273 | "port": 8080 274 | } 275 | }, 276 | "env": [ 277 | { 278 | "name": "DATABASE_SERVICE_NAME", 279 | "value": "${DATABASE_SERVICE_NAME}" 280 | }, 281 | { 282 | "name": "POSTGRESQL_USER", 283 | "valueFrom": { 284 | "secretKeyRef" : { 285 | "name" : "${NAME}", 286 | "key" : "database-user" 287 | } 288 | } 289 | }, 290 | { 291 | "name": "POSTGRESQL_PASSWORD", 292 | "valueFrom": { 293 | "secretKeyRef" : { 294 | "name" : "${NAME}", 295 | "key" : "database-password" 296 | } 297 | } 298 | }, 299 | { 300 | "name": "POSTGRESQL_DATABASE", 301 | "value": "${DATABASE_NAME}" 302 | }, 303 | { 304 | "name": "SECRET_KEY_BASE", 305 | "valueFrom": { 306 | "secretKeyRef" : { 307 | "name" : "${NAME}", 308 | "key" : "keybase" 309 | } 310 | } 311 | }, 312 | { 313 | "name": "POSTGRESQL_MAX_CONNECTIONS", 314 | "value": "${POSTGRESQL_MAX_CONNECTIONS}" 315 | }, 316 | { 317 | "name": "POSTGRESQL_SHARED_BUFFERS", 318 | "value": "${POSTGRESQL_SHARED_BUFFERS}" 319 | }, 320 | { 321 | "name": "APPLICATION_DOMAIN", 322 | "value": "${APPLICATION_DOMAIN}" 323 | }, 324 | { 325 | "name": "APPLICATION_USER", 326 | "valueFrom": { 327 | "secretKeyRef" : { 328 | "name" : "${NAME}", 329 | "key" : "application-user" 330 | } 331 | } 332 | }, 333 | { 334 | "name": "APPLICATION_PASSWORD", 335 | "valueFrom": { 336 | "secretKeyRef" : { 337 | "name" : "${NAME}", 338 | "key" : "application-password" 339 | } 340 | } 341 | }, 342 | { 343 | "name": "RAILS_ENV", 344 | "value": "${RAILS_ENV}" 345 | } 346 | ], 347 | "resources": { 348 | "limits": { 349 | "memory": "${MEMORY_LIMIT}" 350 | } 351 | } 352 | } 353 | ] 354 | } 355 | } 356 | } 357 | }, 358 | { 359 | "kind": "Service", 360 | "apiVersion": "v1", 361 | "metadata": { 362 | "name": "${DATABASE_SERVICE_NAME}", 363 | "annotations": { 364 | "description": "Exposes the database server" 365 | } 366 | }, 367 | "spec": { 368 | "ports": [ 369 | { 370 | "name": "postgresql", 371 | "port": 5432, 372 | "targetPort": 5432 373 | } 374 | ], 375 | "selector": { 376 | "name": "${DATABASE_SERVICE_NAME}" 377 | } 378 | } 379 | }, 380 | { 381 | "kind": "Deployment", 382 | "apiVersion": "apps/v1", 383 | "metadata": { 384 | "name": "${DATABASE_SERVICE_NAME}", 385 | "annotations": { 386 | "description": "Defines how to deploy the database", 387 | "template.alpha.openshift.io/wait-for-ready": "true", 388 | "image.openshift.io/triggers": "[{\"from\":{\"kind\":\"ImageStreamTag\",\"name\":\"postgresql:${POSTGRESQL_VERSION}\", \"namespace\": \"${NAMESPACE}\"},\"fieldPath\": \"spec.template.spec.containers[0].image\"}]" 389 | } 390 | }, 391 | "spec": { 392 | "strategy": { 393 | "type": "Recreate" 394 | }, 395 | "replicas": 1, 396 | "selector": { 397 | "matchLabels": { 398 | "name": "${DATABASE_SERVICE_NAME}" 399 | } 400 | }, 401 | "template": { 402 | "metadata": { 403 | "name": "${DATABASE_SERVICE_NAME}", 404 | "labels": { 405 | "name": "${DATABASE_SERVICE_NAME}" 406 | } 407 | }, 408 | "spec": { 409 | "volumes": [ 410 | { 411 | "name": "data", 412 | "emptyDir": {} 413 | } 414 | ], 415 | "containers": [ 416 | { 417 | "name": "postgresql", 418 | "image": " ", 419 | "ports": [ 420 | { 421 | "containerPort": 5432 422 | } 423 | ], 424 | "readinessProbe": { 425 | "timeoutSeconds": 1, 426 | "initialDelaySeconds": 5, 427 | "exec": { 428 | "command": [ "/usr/libexec/check-container" ] 429 | } 430 | }, 431 | "livenessProbe": { 432 | "timeoutSeconds": 10, 433 | "initialDelaySeconds": 120, 434 | "exec": { 435 | "command": [ "/usr/libexec/check-container", "--live" ] 436 | } 437 | }, 438 | "volumeMounts": [ 439 | { 440 | "name": "data", 441 | "mountPath": "/var/lib/pgsql/data" 442 | } 443 | ], 444 | "env": [ 445 | { 446 | "name": "POSTGRESQL_USER", 447 | "valueFrom": { 448 | "secretKeyRef" : { 449 | "name" : "${NAME}", 450 | "key" : "database-user" 451 | } 452 | } 453 | }, 454 | { 455 | "name": "POSTGRESQL_PASSWORD", 456 | "valueFrom": { 457 | "secretKeyRef" : { 458 | "name" : "${NAME}", 459 | "key" : "database-password" 460 | } 461 | } 462 | }, 463 | { 464 | "name": "POSTGRESQL_DATABASE", 465 | "value": "${DATABASE_NAME}" 466 | }, 467 | { 468 | "name": "POSTGRESQL_MAX_CONNECTIONS", 469 | "value": "${POSTGRESQL_MAX_CONNECTIONS}" 470 | }, 471 | { 472 | "name": "POSTGRESQL_SHARED_BUFFERS", 473 | "value": "${POSTGRESQL_SHARED_BUFFERS}" 474 | } 475 | ], 476 | "resources": { 477 | "limits": { 478 | "memory": "${MEMORY_POSTGRESQL_LIMIT}" 479 | } 480 | } 481 | } 482 | ] 483 | } 484 | } 485 | } 486 | } 487 | ], 488 | "parameters": [ 489 | { 490 | "name": "NAME", 491 | "displayName": "Name", 492 | "description": "The name assigned to all of the frontend objects defined in this template.", 493 | "required": true, 494 | "value": "rails-postgresql-example" 495 | }, 496 | { 497 | "name": "NAMESPACE", 498 | "displayName": "Namespace", 499 | "required": true, 500 | "description": "The OpenShift Namespace where the ImageStream resides.", 501 | "value": "openshift" 502 | }, 503 | { 504 | "name": "RUBY_VERSION", 505 | "displayName": "Ruby Version", 506 | "description": "Version of Ruby image to be used (3.1-ubi8 by default).", 507 | "required": true, 508 | "value": "3.1-ubi8" 509 | }, 510 | { 511 | "name": "POSTGRESQL_VERSION", 512 | "displayName": "Postgresql Version", 513 | "description": "Version of Postgresql image to be used (12-el8 by default).", 514 | "required": true, 515 | "value": "12-el8" 516 | }, 517 | { 518 | "name": "MEMORY_LIMIT", 519 | "displayName": "Memory Limit", 520 | "required": true, 521 | "description": "Maximum amount of memory the Rails container can use.", 522 | "value": "512Mi" 523 | }, 524 | { 525 | "name": "MEMORY_POSTGRESQL_LIMIT", 526 | "displayName": "Memory Limit (PostgreSQL)", 527 | "required": true, 528 | "description": "Maximum amount of memory the PostgreSQL container can use.", 529 | "value": "512Mi" 530 | }, 531 | { 532 | "name": "SOURCE_REPOSITORY_URL", 533 | "displayName": "Git Repository URL", 534 | "required": true, 535 | "description": "The URL of the repository with your application source code.", 536 | "value": "https://github.com/sclorg/rails-ex.git" 537 | }, 538 | { 539 | "name": "SOURCE_REPOSITORY_REF", 540 | "displayName": "Git Reference", 541 | "description": "Set this to a branch name, tag or other ref of your repository if you are not using the default branch." 542 | }, 543 | { 544 | "name": "CONTEXT_DIR", 545 | "displayName": "Context Directory", 546 | "description": "Set this to the relative path to your project if it is not in the root of your repository." 547 | }, 548 | { 549 | "name": "APPLICATION_DOMAIN", 550 | "displayName": "Application Hostname", 551 | "description": "The exposed hostname that will route to the Rails service, if left blank a value will be defaulted.", 552 | "value": "" 553 | }, 554 | { 555 | "name": "GITHUB_WEBHOOK_SECRET", 556 | "displayName": "GitHub Webhook Secret", 557 | "description": "Github trigger secret. A difficult to guess string encoded as part of the webhook URL. Not encrypted.", 558 | "generate": "expression", 559 | "from": "[a-zA-Z0-9]{40}" 560 | }, 561 | { 562 | "name": "SECRET_KEY_BASE", 563 | "displayName": "Secret Key", 564 | "description": "Your secret key for verifying the integrity of signed cookies.", 565 | "generate": "expression", 566 | "from": "[a-z0-9]{127}" 567 | }, 568 | { 569 | "name": "APPLICATION_USER", 570 | "displayName": "Application Username", 571 | "required": true, 572 | "description": "The application user that is used within the sample application to authorize access on pages.", 573 | "value": "openshift" 574 | }, 575 | { 576 | "name": "APPLICATION_PASSWORD", 577 | "displayName": "Application Password", 578 | "required": true, 579 | "description": "The application password that is used within the sample application to authorize access on pages.", 580 | "value": "secret" 581 | }, 582 | { 583 | "name": "RAILS_ENV", 584 | "displayName": "Rails Environment", 585 | "required": true, 586 | "description": "Environment under which the sample application will run. Could be set to production, development or test.", 587 | "value": "production" 588 | }, 589 | { 590 | "name": "DATABASE_SERVICE_NAME", 591 | "required": true, 592 | "displayName": "Database Service Name", 593 | "value": "postgresql" 594 | }, 595 | { 596 | "name": "DATABASE_USER", 597 | "displayName": "Database Username", 598 | "generate": "expression", 599 | "from": "user[A-Z0-9]{3}" 600 | }, 601 | { 602 | "name": "DATABASE_PASSWORD", 603 | "displayName": "Database Password", 604 | "generate": "expression", 605 | "from": "[a-zA-Z0-9]{8}" 606 | }, 607 | { 608 | "name": "DATABASE_NAME", 609 | "required": true, 610 | "displayName": "Database Name", 611 | "value": "root" 612 | }, 613 | { 614 | "name": "POSTGRESQL_MAX_CONNECTIONS", 615 | "displayName": "Maximum Database Connections", 616 | "value": "100" 617 | }, 618 | { 619 | "name": "POSTGRESQL_SHARED_BUFFERS", 620 | "displayName": "Shared Buffer Amount", 621 | "value": "12MB" 622 | }, 623 | { 624 | "name": "RUBYGEM_MIRROR", 625 | "displayName": "Custom RubyGems Mirror URL", 626 | "description": "The custom RubyGems mirror URL", 627 | "value": "" 628 | } 629 | ] 630 | } 631 | -------------------------------------------------------------------------------- /openshift/templates/rails.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "Template", 3 | "apiVersion": "template.openshift.io/v1", 4 | "metadata": { 5 | "name": "rails-example", 6 | "annotations": { 7 | "openshift.io/display-name": "Rails", 8 | "description": "An example Rails application with no database. For more information about using this template, including OpenShift considerations, see https://github.com/sclorg/rails-ex/blob/master/README.md.", 9 | "tags": "quickstart,ruby,rails", 10 | "iconClass": "icon-ruby", 11 | "openshift.io/long-description": "This template defines resources needed to develop a Rails application, including a build configuration, application deployment configuration, and database deployment configuration.", 12 | "openshift.io/provider-display-name": "Red Hat, Inc.", 13 | "openshift.io/documentation-url": "https://github.com/sclorg/rails-ex", 14 | "openshift.io/support-url": "https://access.redhat.com", 15 | "template.openshift.io/bindable": "false" 16 | } 17 | }, 18 | "message": "The following service(s) have been created in your project: ${NAME}.\n\nFor more information about using this template, including OpenShift considerations, see https://github.com/sclorg/dancer-ex/blob/master/README.md.", 19 | "labels": { 20 | "template": "rails-example", 21 | "app": "rails-example" 22 | }, 23 | "objects": [ 24 | { 25 | "kind": "Service", 26 | "apiVersion": "v1", 27 | "metadata": { 28 | "name": "${NAME}", 29 | "annotations": { 30 | "description": "Exposes and load balances the application pods" 31 | } 32 | }, 33 | "spec": { 34 | "ports": [ 35 | { 36 | "name": "web", 37 | "port": 8080, 38 | "targetPort": 8080 39 | } 40 | ], 41 | "selector": { 42 | "name": "${NAME}" 43 | } 44 | } 45 | }, 46 | { 47 | "kind": "Route", 48 | "apiVersion": "route.openshift.io/v1", 49 | "metadata": { 50 | "name": "${NAME}" 51 | }, 52 | "spec": { 53 | "host": "${APPLICATION_DOMAIN}", 54 | "to": { 55 | "kind": "Service", 56 | "name": "${NAME}" 57 | } 58 | } 59 | }, 60 | { 61 | "kind": "ImageStream", 62 | "apiVersion": "image.openshift.io/v1", 63 | "metadata": { 64 | "name": "${NAME}", 65 | "annotations": { 66 | "description": "Keeps track of changes in the application image" 67 | } 68 | } 69 | }, 70 | { 71 | "kind": "BuildConfig", 72 | "apiVersion": "build.openshift.io/v1", 73 | "metadata": { 74 | "name": "${NAME}", 75 | "annotations": { 76 | "description": "Defines how to build the application", 77 | "template.alpha.openshift.io/wait-for-ready": "true" 78 | } 79 | }, 80 | "spec": { 81 | "source": { 82 | "type": "Git", 83 | "git": { 84 | "uri": "${SOURCE_REPOSITORY_URL}", 85 | "ref": "${SOURCE_REPOSITORY_REF}" 86 | }, 87 | "contextDir": "${CONTEXT_DIR}" 88 | }, 89 | "strategy": { 90 | "type": "Source", 91 | "sourceStrategy": { 92 | "from": { 93 | "kind": "ImageStreamTag", 94 | "namespace": "${NAMESPACE}", 95 | "name": "ruby:${RUBY_VERSION}" 96 | }, 97 | "env": [ 98 | { 99 | "name": "RUBYGEM_MIRROR", 100 | "value": "${RUBYGEM_MIRROR}" 101 | } 102 | ] 103 | } 104 | }, 105 | "output": { 106 | "to": { 107 | "kind": "ImageStreamTag", 108 | "name": "${NAME}:latest" 109 | } 110 | }, 111 | "triggers": [ 112 | { 113 | "type": "ImageChange" 114 | }, 115 | { 116 | "type": "ConfigChange" 117 | }, 118 | { 119 | "type": "GitHub", 120 | "github": { 121 | "secret": "${GITHUB_WEBHOOK_SECRET}" 122 | } 123 | } 124 | ] 125 | } 126 | }, 127 | { 128 | "kind": "Deployment", 129 | "apiVersion": "apps/v1", 130 | "metadata": { 131 | "name": "${NAME}", 132 | "annotations": { 133 | "description": "Defines how to deploy the application server", 134 | "template.alpha.openshift.io/wait-for-ready": "true", 135 | "image.openshift.io/triggers": "[{\"from\":{\"kind\":\"ImageStreamTag\",\"name\":\"${NAME}:latest\"},\"fieldPath\": \"spec.template.spec.containers[0].image\"}]" 136 | } 137 | }, 138 | "spec": { 139 | "strategy": { 140 | "type": "RollingUpdate" 141 | }, 142 | "replicas": 1, 143 | "selector": { 144 | "matchLabels": { 145 | "name": "${NAME}" 146 | } 147 | }, 148 | "template": { 149 | "metadata": { 150 | "name": "${NAME}", 151 | "labels": { 152 | "name": "${NAME}" 153 | } 154 | }, 155 | "spec": { 156 | "containers": [ 157 | { 158 | "name": "rails-example", 159 | "image": " ", 160 | "ports": [ 161 | { 162 | "containerPort": 8080 163 | } 164 | ], 165 | "readinessProbe": { 166 | "timeoutSeconds": 3, 167 | "initialDelaySeconds": 3, 168 | "httpGet": { 169 | "path": "/", 170 | "port": 8080 171 | } 172 | }, 173 | "livenessProbe": { 174 | "timeoutSeconds": 3, 175 | "initialDelaySeconds": 30, 176 | "httpGet": { 177 | "path": "/", 178 | "port": 8080 179 | } 180 | }, 181 | "env": [ 182 | { 183 | "name": "RAILS_ENV", 184 | "value": "${RAILS_ENV}" 185 | } 186 | ], 187 | "resources": { 188 | "limits": { 189 | "memory": "${MEMORY_LIMIT}" 190 | } 191 | } 192 | } 193 | ] 194 | } 195 | } 196 | } 197 | } 198 | ], 199 | "parameters": [ 200 | { 201 | "name": "NAME", 202 | "displayName": "Name", 203 | "description": "The name assigned to all of the frontend objects defined in this template.", 204 | "required": true, 205 | "value": "rails-example" 206 | }, 207 | { 208 | "name": "NAMESPACE", 209 | "displayName": "Namespace", 210 | "description": "The OpenShift Namespace where the ImageStream resides.", 211 | "required": true, 212 | "value": "openshift" 213 | }, 214 | { 215 | "name": "RUBY_VERSION", 216 | "displayName": "Ruby Version", 217 | "description": "Version of Ruby image to be used (3.1-ubi8 by default).", 218 | "required": true, 219 | "value": "3.1-ubi8" 220 | }, 221 | { 222 | "name": "MEMORY_LIMIT", 223 | "displayName": "Memory Limit", 224 | "description": "Maximum amount of memory the container can use.", 225 | "required": true, 226 | "value": "512Mi" 227 | }, 228 | { 229 | "name": "SOURCE_REPOSITORY_URL", 230 | "displayName": "Git Repository URL", 231 | "required": true, 232 | "description": "The URL of the repository with your application source code.", 233 | "value": "https://github.com/sclorg/rails-ex.git" 234 | }, 235 | { 236 | "name": "SOURCE_REPOSITORY_REF", 237 | "displayName": "Git Reference", 238 | "description": "Set this to a branch name, tag or other ref of your repository if you are not using the default branch." 239 | }, 240 | { 241 | "name": "CONTEXT_DIR", 242 | "displayName": "Context Directory", 243 | "description": "Set this to the relative path to your project if it is not in the root of your repository." 244 | }, 245 | { 246 | "name": "APPLICATION_DOMAIN", 247 | "displayName": "Application Hostname", 248 | "description": "The exposed hostname that will route to the Rails service, if left blank a value will be defaulted.", 249 | "value": "" 250 | }, 251 | { 252 | "name": "GITHUB_WEBHOOK_SECRET", 253 | "displayName": "GitHub Webhook Secret", 254 | "description": "Github trigger secret. A difficult to guess string encoded as part of the webhook URL. Not encrypted.", 255 | "generate": "expression", 256 | "from": "[a-zA-Z0-9]{40}" 257 | }, 258 | { 259 | "name": "SECRET_KEY_BASE", 260 | "displayName": "Secret Key", 261 | "description": "Your secret key for verifying the integrity of signed cookies.", 262 | "generate": "expression", 263 | "from": "[a-z0-9]{127}" 264 | }, 265 | { 266 | "name": "RAILS_ENV", 267 | "displayName": "Rails Environment", 268 | "required": true, 269 | "description": "Environment under which the sample application will run. Could be set to production, development or test.", 270 | "value": "production" 271 | }, 272 | { 273 | "name": "RUBYGEM_MIRROR", 274 | "displayName": "Custom RubyGems Mirror URL", 275 | "description": "The custom RubyGems mirror URL", 276 | "value": "" 277 | } 278 | ] 279 | } 280 | -------------------------------------------------------------------------------- /public/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The page you were looking for doesn't exist (404) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

The page you were looking for doesn't exist.

62 |

You may have mistyped the address or the page may have moved.

63 |
64 |

If you are the application owner check the logs for more information.

65 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /public/422.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The change you wanted was rejected (422) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

The change you wanted was rejected.

62 |

Maybe you tried to change something you didn't have access to.

63 |
64 |

If you are the application owner check the logs for more information.

65 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /public/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | We're sorry, but something went wrong (500) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

We're sorry, but something went wrong.

62 |
63 |

If you are the application owner check the logs for more information.

64 |
65 | 66 | 67 | -------------------------------------------------------------------------------- /public/apple-touch-icon-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sclorg/rails-ex/482ef27972d3f594b1e3a1481c1113075238496d/public/apple-touch-icon-precomposed.png -------------------------------------------------------------------------------- /public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sclorg/rails-ex/482ef27972d3f594b1e3a1481c1113075238496d/public/apple-touch-icon.png -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sclorg/rails-ex/482ef27972d3f594b1e3a1481c1113075238496d/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Welcome to OpenShift 7 | 8 | 9 | 207 | 208 | 209 | 210 | 211 |
212 |
213 |

Welcome to your Rails application on OpenShift

214 |
215 | 216 | 217 |
218 |
219 |
220 |

How to use this example application

221 |

For instructions on how to use this application with OpenShift, start by reading the Developer Guide.

222 | 223 |

Deploying code changes

224 |

225 | The source code for this application is available to be forked from the OpenShift GitHub repository. 226 | You can configure a webhook in your repository to make OpenShift automatically start a build whenever you push your code: 227 |

228 | 229 |
    230 |
  1. From the Web Console homepage, navigate to your project
  2. 231 |
  3. Click on Browse > Builds
  4. 232 |
  5. Click the link with your BuildConfig name
  6. 233 |
  7. Click the Configuration tab
  8. 234 |
  9. Click the "Copy to clipboard" icon to the right of the "GitHub webhook URL" field
  10. 235 |
  11. Navigate to your repository on GitHub and click on repository settings > webhooks > Add webhook
  12. 236 |
  13. Paste your webhook URL provided by OpenShift
  14. 237 |
  15. Leave the defaults for the remaining fields — that's it!
  16. 238 |
239 |

After you save your webhook, if you refresh your settings page you can see the status of the ping that Github sent to OpenShift to verify it can reach the server.

240 |

Note: adding a webhook requires your OpenShift server to be reachable from GitHub.

241 | 242 |

Working in your local Git repository

243 |

If you forked the application from the OpenShift GitHub example, you'll need to manually clone the repository to your local system. Copy the application's source code Git URL and then run:

244 | 245 |
$ git clone <git_url> <directory_to_create>
246 | 
247 | # Within your project directory
248 | # Commit your changes and push to OpenShift
249 | 
250 | $ git commit -a -m 'Some commit message'
251 | $ git push
252 | 253 |

After pushing changes, you'll need to manually trigger a build if you did not setup a webhook as described above.

254 | 255 |

Expanding on sample app

256 |

257 | This app also includes a sample blogging implementation. 258 |

259 |

260 | In order to access the example blog application, you have to remove the 261 | public/index.html file which serves as the welcome page. Another option is to make a 262 | request directly to `/articles` which will give you access to the blog example. If you did not modify the APPLICATION_USER 263 | and APPLICATION_PASSWORD parameter values in the template, then the default login/password is openshift/secret. 264 |

265 |

266 | It will also be necessary to define a database service for the application to use. The config/database.yml file used by rails was set up in such a way that it will accept environment variables for database connection information. After creating a PostgreSQL database service in your project, you can add the following environment variables to your deploymentConfig to ensure all your frontend pods have access to these environment variables. 267 | Note: the rails-postgresql.json template creates the database service and environment variables for you. 268 | 269 |

270 | oc env dc/rails-frontend DATABASE_SERVICE_NAME=<database service name>
271 | oc env dc/rails-frontend <DATABASE_SERVICE_NAME>_SERVICE_HOST=<database service ip>
272 | oc env dc/rails-frontend <DATABASE_SERVICE_NAME>_SERVICE_PORT=<database service port>
273 | oc env dc/rails-frontend POSTGRESQL_DATABASE=<your created database>
274 | oc env dc/rails-frontend POSTGRESQL_USER=<your database user>
275 | oc env dc/rails-frontend POSTGRESQL_PASSWORD=<your database user's password>
276 | 
277 |

278 |

279 | Note: If the database service is created in the same project as the frontend pod, 280 | the *_SERVICE_HOST and *_SERVICE_PORT environment variables will be automatically 281 | created. 282 |

283 |

284 | You will need to redeploy your application in order to pick up the new environment variables. You can force a deployment 285 | by running: 286 |

287 | oc deploy rails-frontend --latest
288 | 
289 |

290 | 291 |
292 | 293 |
294 |
295 | 296 |

Managing your application

297 | 298 |

Documentation on how to manage your application from the Web Console or Command Line is available at the Developer Guide.

299 | 300 |

Web Console

301 |

You can use the Web Console to view the state of your application components and launch new builds.

302 | 303 |

Command Line

304 |

With the OpenShift command line interface (CLI), you can create applications and manage projects from a terminal.

305 | 306 |

Development Resources

307 | 315 | 316 | 317 |
318 |
319 | 320 | 323 |
324 | 325 | 326 | 327 | 328 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file 2 | -------------------------------------------------------------------------------- /test/application_system_test_case.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | 3 | class ApplicationSystemTestCase < ActionDispatch::SystemTestCase 4 | driven_by :selenium, using: :chrome, screen_size: [1400, 1400] 5 | end 6 | -------------------------------------------------------------------------------- /test/controllers/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sclorg/rails-ex/482ef27972d3f594b1e3a1481c1113075238496d/test/controllers/.keep -------------------------------------------------------------------------------- /test/controllers/articles_controller_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class ArticlesControllerTest < ActionDispatch::IntegrationTest 4 | end 5 | -------------------------------------------------------------------------------- /test/controllers/comments_controller_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class CommentsControllerTest < ActionDispatch::IntegrationTest 4 | setup do 5 | @comment = comments(:one) 6 | end 7 | 8 | end 9 | -------------------------------------------------------------------------------- /test/controllers/welcome_controller_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class WelcomeControllerTest < ActionDispatch::IntegrationTest 4 | test "should get index" do 5 | get welcome_index_url 6 | assert_response :success 7 | end 8 | 9 | end 10 | -------------------------------------------------------------------------------- /test/fixtures/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sclorg/rails-ex/482ef27972d3f594b1e3a1481c1113075238496d/test/fixtures/.keep -------------------------------------------------------------------------------- /test/fixtures/articles.yml: -------------------------------------------------------------------------------- 1 | # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html 2 | 3 | one: 4 | title: MyString 5 | body: MyText 6 | 7 | two: 8 | title: MyString 9 | body: MyText 10 | -------------------------------------------------------------------------------- /test/fixtures/comments.yml: -------------------------------------------------------------------------------- 1 | # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html 2 | 3 | one: 4 | commenter: MyString 5 | body: MyText 6 | 7 | two: 8 | commenter: MyString 9 | body: MyText 10 | -------------------------------------------------------------------------------- /test/fixtures/files/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sclorg/rails-ex/482ef27972d3f594b1e3a1481c1113075238496d/test/fixtures/files/.keep -------------------------------------------------------------------------------- /test/helpers/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sclorg/rails-ex/482ef27972d3f594b1e3a1481c1113075238496d/test/helpers/.keep -------------------------------------------------------------------------------- /test/integration/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sclorg/rails-ex/482ef27972d3f594b1e3a1481c1113075238496d/test/integration/.keep -------------------------------------------------------------------------------- /test/mailers/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sclorg/rails-ex/482ef27972d3f594b1e3a1481c1113075238496d/test/mailers/.keep -------------------------------------------------------------------------------- /test/models/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sclorg/rails-ex/482ef27972d3f594b1e3a1481c1113075238496d/test/models/.keep -------------------------------------------------------------------------------- /test/models/article_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class ArticleTest < ActiveSupport::TestCase 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /test/models/comment_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class CommentTest < ActiveSupport::TestCase 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /test/system/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sclorg/rails-ex/482ef27972d3f594b1e3a1481c1113075238496d/test/system/.keep -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../../config/environment', __FILE__) 2 | require 'rails/test_help' 3 | 4 | class ActiveSupport::TestCase 5 | # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order. 6 | fixtures :all 7 | 8 | # Add more helper methods to be used by all tests here... 9 | end 10 | -------------------------------------------------------------------------------- /tests/test_rails.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import pytest 4 | from pathlib import Path 5 | 6 | from container_ci_suite.openshift import OpenShiftAPI 7 | 8 | test_dir = Path(os.path.abspath(os.path.dirname(__file__))) 9 | 10 | VERSION=os.getenv("SINGLE_VERSION") 11 | if not VERSION: 12 | VERSION="3.1-ubi8" 13 | 14 | class TestRailsAppExTemplate: 15 | 16 | def setup_method(self): 17 | self.oc_api = OpenShiftAPI(pod_name_prefix="rails-example") 18 | json_raw_file = self.oc_api.get_raw_url_for_json( 19 | container="s2i-ruby-container", dir="imagestreams", filename="ruby-rhel.json" 20 | ) 21 | self.oc_api.import_is(path=json_raw_file, name="ruby") 22 | 23 | def teardown_method(self): 24 | self.oc_api.delete_project() 25 | 26 | def test_template_inside_cluster(self): 27 | if VERSION.startswith("3.3"): 28 | branch_to_test = "3.3" 29 | else: 30 | branch_to_test = "master" 31 | expected_output = "Welcome to your Rails application" 32 | template_json = self.oc_api.get_raw_url_for_json( 33 | container="rails-ex", branch=branch_to_test, dir="openshift/templates", filename="rails.json" 34 | ) 35 | assert self.oc_api.deploy_template( 36 | template=template_json, name_in_template="rails-example", expected_output=expected_output, 37 | openshift_args=[f"SOURCE_REPOSITORY_REF={branch_to_test}", f"RUBY_VERSION={VERSION}", "NAME=rails-example"] 38 | ) 39 | assert self.oc_api.template_deployed(name_in_template="rails-example") 40 | assert self.oc_api.check_response_inside_cluster( 41 | name_in_template="rails-example", expected_output=expected_output 42 | ) 43 | 44 | def test_template_by_request(self): 45 | if VERSION.startswith("3.3"): 46 | branch_to_test = "3.3" 47 | else: 48 | branch_to_test = "master" 49 | expected_output = "Welcome to your Rails application" 50 | template_json = self.oc_api.get_raw_url_for_json( 51 | container="rails-ex", branch=branch_to_test, dir="openshift/templates", filename="rails.json" 52 | ) 53 | assert self.oc_api.deploy_template( 54 | template=template_json, name_in_template="rails-example", expected_output=expected_output, 55 | openshift_args=[f"SOURCE_REPOSITORY_REF={branch_to_test}", f"RUBY_VERSION={VERSION}", "NAME=rails-example"] 56 | ) 57 | assert self.oc_api.template_deployed(name_in_template="rails-example") 58 | assert self.oc_api.check_response_outside_cluster( 59 | name_in_template="rails-example", expected_output=expected_output 60 | ) 61 | -------------------------------------------------------------------------------- /tests/test_rails_postgresql.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import pytest 4 | from pathlib import Path 5 | 6 | from container_ci_suite.openshift import OpenShiftAPI 7 | 8 | test_dir = Path(os.path.abspath(os.path.dirname(__file__))) 9 | 10 | VERSION=os.getenv("SINGLE_VERSION") 11 | if not VERSION: 12 | VERSION="3.1-ubi8" 13 | 14 | class TestRailsAppWithPostgreSQLExTemplate: 15 | 16 | def setup_method(self): 17 | self.oc_api = OpenShiftAPI(pod_name_prefix="rails-example") 18 | json_raw_file = self.oc_api.get_raw_url_for_json( 19 | container="s2i-ruby-container", dir="imagestreams", filename="ruby-rhel.json" 20 | ) 21 | self.oc_api.import_is(path=json_raw_file, name="ruby") 22 | json_raw_file = self.oc_api.get_raw_url_for_json( 23 | container="postgresql-container", dir="imagestreams", filename="postgresql-rhel.json" 24 | ) 25 | self.oc_api.import_is(path=json_raw_file, name="postgresql") 26 | 27 | def teardown_method(self): 28 | self.oc_api.delete_project() 29 | 30 | def test_template_inside_cluster(self): 31 | if VERSION.startswith("3.3"): 32 | branch_to_test = "3.3" 33 | else: 34 | branch_to_test = "master" 35 | expected_output = "Welcome to your Rails application" 36 | template_json = self.oc_api.get_raw_url_for_json( 37 | container="rails-ex", branch=branch_to_test, dir="openshift/templates", filename="rails-postgresql-persistent.json" 38 | ) 39 | assert self.oc_api.deploy_template( 40 | template=template_json, name_in_template="rails-example", expected_output=expected_output, 41 | openshift_args=[ 42 | f"SOURCE_REPOSITORY_REF={branch_to_test}", 43 | f"RUBY_VERSION={VERSION}", 44 | "NAME=rails-example", 45 | "POSTGRESQL_VERSION=12-el8" 46 | ] 47 | ) 48 | assert self.oc_api.template_deployed(name_in_template="rails-example") 49 | assert self.oc_api.check_response_inside_cluster( 50 | name_in_template="rails-example", expected_output=expected_output 51 | ) 52 | 53 | def test_template_by_request(self): 54 | if VERSION.startswith("3.3"): 55 | branch_to_test = "3.3" 56 | else: 57 | branch_to_test = "master" 58 | expected_output = "Welcome to your Rails application" 59 | template_json = self.oc_api.get_raw_url_for_json( 60 | container="rails-ex", branch=branch_to_test, dir="openshift/templates", filename="rails-postgresql-persistent.json" 61 | ) 62 | assert self.oc_api.deploy_template( 63 | template=template_json, name_in_template="rails-example", expected_output=expected_output, 64 | openshift_args=[ 65 | f"SOURCE_REPOSITORY_REF={branch_to_test}", 66 | f"RUBY_VERSION={VERSION}", 67 | "NAME=rails-example", 68 | "POSTGRESQL_VERSION=12-el8" 69 | ] 70 | ) 71 | assert self.oc_api.template_deployed(name_in_template="rails-example") 72 | assert self.oc_api.check_response_outside_cluster( 73 | name_in_template="rails-example", expected_output=expected_output 74 | ) 75 | -------------------------------------------------------------------------------- /vendor/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sclorg/rails-ex/482ef27972d3f594b1e3a1481c1113075238496d/vendor/.keep -------------------------------------------------------------------------------- /vendor/assets/javascripts/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sclorg/rails-ex/482ef27972d3f594b1e3a1481c1113075238496d/vendor/assets/javascripts/.keep -------------------------------------------------------------------------------- /vendor/assets/stylesheets/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sclorg/rails-ex/482ef27972d3f594b1e3a1481c1113075238496d/vendor/assets/stylesheets/.keep --------------------------------------------------------------------------------