#+TITLE: ROSA Ruby On Rails Workshop #+AUTHOR: James Blair #+DATE: <2023-08-18 Fri 13:30> * Introduction This document captures the setup steps for a 90-minute, hands-on [[https://rubyonrails.org/][Ruby On Rails]] workshop on [[https://www.redhat.com/en/technologies/cloud-computing/openshift][Openshift]]. Within the session, participants will: - Gain an understanding of OpenShift and containers. - Work with a Ruby codebase in [[https://bitbucket.org/product/][Bitbucket]]. - Deploy the application on Openshift using several methods. - Create continuous delivery pipelines with [[https://tekton.dev/docs/][Tekton]]. * Pre-requisites This guide assumes you have an existing Openshift 4.10+ cluster with cluster admin permissions. In my case I have a Red Hat OpenShift on AWS (ROSA) cluster provisioned through the Red Hat [[https://demo.redhat.com][demo system]]. * 1 - Preparing the cluster To get start let's ensure we are logged in to the cluster in our terminal with the ~oc~ cli. #+begin_src bash oc login --server --token #+end_src * 2 - Deploy Bitbucket Now that we're logged into the cluster, let's create the namespace to deploy Bitbucket into. #+begin_src bash :results output oc new-project bitbucket #+end_src #+RESULTS: #+begin_example Now using project "bitbucket" on server "https://api.cluster-dkxhl.dkxhl.sandbox1652.opentlc.com:6443". You can add applications to this project with the 'new-app' command. For example, try: oc new-app rails-postgresql-example to build a new example application in Ruby. Or use kubectl to deploy a simple Kubernetes application: kubectl create deployment hello-node --image=k8s.gcr.io/e2e-test-images/agnhost:2.33 -- /agnhost serve-hostname #+end_example Once the namespace is created we can deploy Bitbucket using the official Bitbucket image from Atlassian. #+begin_src bash :results output cat << EOF | oc --namespace bitbucket apply --filename - kind: Deployment apiVersion: apps/v1 metadata: name: bitbucket namespace: bitbucket labels: app: bitbucket spec: replicas: 1 selector: matchLabels: deployment: bitbucket template: metadata: labels: deployment: bitbucket spec: volumes: - name: bitbucket-volume emptyDir: {} containers: - name: bitbucket image: docker.io/atlassian/bitbucket-server@sha256:30556d63fc935a1c3c9da41e6fff617e452ad7a52060a92b6a20f9179dd637a5 ports: - containerPort: 7990 protocol: TCP - containerPort: 7999 protocol: TCP resources: limits: cpu: 500m memory: 4096Mi volumeMounts: - name: bitbucket-volume mountPath: /var/atlassian/application-data/bitbucket terminationMessagePath: /dev/termination-log terminationMessagePolicy: File imagePullPolicy: IfNotPresent restartPolicy: Always terminationGracePeriodSeconds: 30 dnsPolicy: ClusterFirst securityContext: {} schedulerName: default-scheduler strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 25% maxSurge: 25% revisionHistoryLimit: 10 progressDeadlineSeconds: 600 EOF #+end_src #+RESULTS: : deployment.apps/bitbucket created Now, let's verify that the Bitbucket pod started successfully. #+begin_src bash :results output oc --namespace bitbucket get pods #+end_src #+RESULTS: : NAME READY STATUS RESTARTS AGE : bitbucket-74bc96b849-5nbvl 1/1 Running 0 45s As this is running successfully, let's expose it with a ~route~ so that we can access it from our web browser. #+begin_src bash :results output oc --namespace bitbucket create route edge bitbucket --service=bitbucket --port=7990 oc --namespace bitbucket get route #+end_src #+RESULTS: : route.route.openshift.io/bitbucket created : NAME HOST/PORT PATH SERVICES PORT TERMINATION WILDCARD : bitbucket bitbucket-bitbucket.apps.cluster-dkxhl.dkxhl.sandbox1652.opentlc.com bitbucket 7990 edge None Once we open the Bitbucket route in our browser, we need to follow a short setup process manually before we can continue with the rest of our automation. 1. Select your language ~English (United States)~. 2. Select ~internal~ and click ~Next~. You'll then be prompted for an Atlassian license key. For the purposes of this workshop, we'll be generating a new trial license [[https://my.atlassian.com/license/evaluation][here]]. Copy the ~Server ID~ into the Bitbucket setup screen and click ~Generate License~. Copy the generated license key into the text box for the Bitbucket license key and click ~Next~. On the Bitbucket setup screen enter details for your administrative user and click ~Go to Bitbucket~. * 3 - Configure Bitbucket With our Bitbucket server successfully deployed, let's configure it for the workshop. First step is to create additional users. #+begin_src bash :results none source .env bitbucket_route=$(oc get route --namespace bitbucket | awk '{print $2}' | tail -n 1) for user in {1..30}; do echo curl --user "admin:${bitbucket_password}" \ --header "'Content-Type: application/json'" \ --header "'X-Atlassian-Token: nocheck'" \ --request "POST" \ "\"https://${bitbucket_route}/rest/api/latest/admin/users?name=user${user}&displayName=user${user}&emailAddress=user${user}%40example.com&password=${bitbucket_user_password}\"" >> users.sh done chmod +x users.sh && ./users.sh && rm users.sh #+end_src Each of these users will be forking a copy of a Ruby on Rails codebase, so let's now create that codebase now. #+begin_src bash :results none source .env bitbucket_route=$(oc get route --namespace bitbucket | awk '{print $2}' | tail -n 1) echo curl --user "admin:${bitbucket_password}" \ --header "'Content-Type: application/json'" \ --data "'{ \"key\": \"MSD\", \"name\": \"Rails Team\", \"description\": \"Rails!\"}'" \ "https://${bitbucket_route}/rest/api/latest/projects" > project.sh echo curl --user "admin:${bitbucket_password}" \ --header "'Content-Type: application/json'" \ --data "'{\"name\": \"rails-example\",\"scmId\": \"git\", \"forkable\": true, \"public\": true }'" \ "https://${bitbucket_route}/rest/api/latest/projects/${project_key}/repos" >> project.sh chmod +x project.sh && ./project.sh && rm project.sh git clone https://github.com/sclorg/rails-ex.git cd rails-ex git remote set-url origin "https://admin:${bitbucket_password}@${bitbucket_route}/scm/msd/rails-example.git" git push -u origin HEAD:master && cd ../ && rm -rf rails-ex #+end_src * 4 - Install openshift pipelines operator Once bitbucket is installed and is setup with the users and codebase our workshop will use lets install the [[https://docs.openshift.com/container-platform/4.10/cicd/pipelines/understanding-openshift-pipelines.html][OpenShift Pipelines]] operator so our workshop participants will be able to create and run Tekton CI/CD pipelines during the workshop. The first step for installing the operator is to create a subscription #+begin_src bash :results output cat << EOF | oc apply --filename - apiVersion: operators.coreos.com/v1alpha1 kind: Subscription metadata: name: openshift-pipelines-operator namespace: openshift-operators spec: channel: latest name: openshift-pipelines-operator-rh source: redhat-operators sourceNamespace: openshift-marketplace EOF #+end_src #+RESULTS: : subscription.operators.coreos.com/openshift-pipelines-operator configured * 5 - Install openshift web terminal operator Another helpful operator that we will use during the workshop is the [[https://cloud.redhat.com/blog/a-deeper-look-at-the-web-terminal-operator-1][OpenShift Web Terminal]]. This is a handy way to access a terminal directly within the OpenShift Web Console. #+begin_src bash :results output cat << EOF | oc apply --filename - apiVersion: operators.coreos.com/v1alpha1 kind: Subscription metadata: name: web-terminal namespace: openshift-operators spec: channel: fast installPlanApproval: Automatic name: web-terminal source: redhat-operators sourceNamespace: openshift-marketplace EOF #+end_src #+RESULTS: : subscription.operators.coreos.com/web-terminal created * 6 - Install openshift serverless operator For our final cluster setup task we will install the [[https://www.redhat.com/en/technologies/cloud-computing/openshift/serverless][OpenShift Serverless]] operator. We'll use this during the workshop to show just how easy it is to convert a traditional Ruby application deployment into a serverless scale to zero application. #+begin_src bash :results output cat << EOF | oc apply --filename - apiVersion: operators.coreos.com/v1alpha1 kind: Subscription metadata: name: serverless-operator namespace: openshift-operators spec: channel: stable name: serverless-operator source: redhat-operators sourceNamespace: openshift-marketplace EOF #+end_src #+RESULTS: : subscription.operators.coreos.com/serverless-operator created Once the operator is installed we just need to enable ~knative~ serving. #+begin_src bash :results output cat << EOF | oc apply --filename - apiVersion: operator.knative.dev/v1beta1 kind: KnativeServing metadata: name: knative-serving namespace: knative-serving EOF #+end_src #+RESULTS: