From 84a10fd0c0d6998454c843ce8de67a4b5446e145 Mon Sep 17 00:00:00 2001 From: "R. Tyler Croy" Date: Fri, 22 Dec 2017 11:34:32 -0800 Subject: [PATCH 1/4] Switch to the new docker image in the codevalet org on docker hub --- k8s/jenkins.yaml.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/k8s/jenkins.yaml.template b/k8s/jenkins.yaml.template index fdb09d6..afd1ca2 100644 --- a/k8s/jenkins.yaml.template +++ b/k8s/jenkins.yaml.template @@ -87,7 +87,7 @@ items: runAsUser: 0 containers: - name: "jenkins-@@USER@@" - image: "rtyler/codevalet-master:latest" + image: "codevalet/master:latest" imagePullPolicy: Always ports: - containerPort: 80 From 018b7a082859d21bf1c2522c9c2ceed4a2e37098 Mon Sep 17 00:00:00 2001 From: "R. Tyler Croy" Date: Fri, 22 Dec 2017 11:34:56 -0800 Subject: [PATCH 2/4] Embed a Jenkins Minute in the home page for a little more interesting stuff Also fleshing out the doc page a bit more, need to figure out what I'm going to do there. --- webapp/views/doc.haml | 115 ++++++++++++++++++++++------------------ webapp/views/index.haml | 7 ++- 2 files changed, 67 insertions(+), 55 deletions(-) diff --git a/webapp/views/doc.haml b/webapp/views/doc.haml index aa16e09..f29a6bb 100644 --- a/webapp/views/doc.haml +++ b/webapp/views/doc.haml @@ -3,86 +3,95 @@ { :name => 'Ubuntu 16.04', :labels => ['ubuntu', 'linux', 'docker'], - :capabilities => '', + :capabilities => ['Docker-enabled'], }, { :name => 'FreeBSD 11.1', :labels => ['freebsd', 'bsd'], - :capabilities => '', + :capabilities => [], }, ] .container .col-md-10 .row - %h2 - Overview .container .row - %p - Code Valet is powered by - %a{:href => 'https://jenkins.io'} - Jenkins® 2 - with - %a{:href => 'https://jenkins.io/doc/book/pipeline'} - Jenkins Pipeline. + .col-lg-12 + %h2 + Overview + %p + Code Valet is powered by + %a{:href => 'https://jenkins.io'} + Jenkins® 2 + with + %a{:href => 'https://jenkins.io/doc/book/pipeline'} + Jenkins Pipeline. .row - %h3 - Features enabled - :markdown - The current list of features enabled on Code Valet, which can be - used in a `Jenkinsfile` are: + .col-lg-12 + %h3 + Features enabled + %p + :markdown + The current list of features enabled on Code Valet, which can be + used in a `Jenkinsfile` are: - * XML (JUnit) test reporting integration via the `junit` step. - * Embedded status badges, such as: [![Build Status](https://codevalet.io/u/codevalet/job/CodeValet/job/codevalet/job/master/badge/icon)](https://codevalet.io/u/codevalet/blue/organizations/jenkins/CodeValet%2Fcodevalet/activity) + * XML (JUnit) test reporting integration via the `junit` step. + * Embedded status badges, such as: [![Build Status](https://codevalet.codevalet.io/job/codevalet/job/master/badge/icon)](https://codevalet.codevalet.io/job/codevalet/job/master/) .row - %h2 - Platforms + .col-lg-12 + %h2 + Platforms - .container - .row - %p - Code Valet provides ephemeral execution environments, dedicated to - each user or organization. This provides the best trade-off between - performance and reliability using the tools currently available. - %p - %table.table - %thead + %p + Code Valet provides ephemeral execution environments, dedicated to + each user or organization. This provides the best trade-off between + performance and reliability using the tools currently available. + %p + %table.table + %thead + %tr + %th + Platform + %th + Capabilities + %th + Example + %code + Jenkinsfile + %tbody + - platforms.each do |p| %tr - %th - Platform - %th - Capabilities - %th - Example - %tbody - - platforms.each do |p| - %tr - %td + %td + %p %strong= p[:name] + %p + Labels: %ul - p[:labels].each do |label| %li %code= label - %td - = p[:capabilities] - %td - %pre - %code - :plain - pipeline { - agent { label '#{p[:labels].first}' } - stages { - stage('Build') { - steps { - sh 'uname -a' - sh 'cat /etc/issue' - } + %td + - p[:capabilities].each do |cap| + %p + = cap + %td + %pre + %code + :plain + pipeline { + agent { label '#{p[:labels].first}' } + stages { + stage('Build') { + steps { + sh 'uname -a' + sh 'cat /etc/issue' } } } + } diff --git a/webapp/views/index.haml b/webapp/views/index.haml index 607278e..a09b6ab 100644 --- a/webapp/views/index.haml +++ b/webapp/views/index.haml @@ -38,8 +38,11 @@ %a.dropdown-item{:href => "https://#{monkey}.codevalet.io/blue"} = monkey .row - .col-md-12 - %img.img-fluid{:src => '/images/create-new-pipeline.png'} + .col-lg-12.text-center + %iframe{:width => 800, :height => 400, :frameborder => 0, :gesture => :media, + :allow => 'encrypted-media', :allowfullscreen => '', + :src => 'https://www.youtube-nocookie.com/embed/FhDomw6BaHU'} + %img.img-fluid{:src => '/images/create-new-pipeline.png'} .row .col-md-12 From 452e81c0d254725e449bc3016f738b645adddf3f Mon Sep 17 00:00:00 2001 From: "R. Tyler Croy" Date: Sat, 23 Dec 2017 14:38:50 -0800 Subject: [PATCH 3/4] Persist sessions using a consistent session secret and memcached Fixes #79 --- docker-compose.yml | 14 +++++++++++++- webapp/Gemfile | 24 ++++++++++++++++++++---- webapp/Gemfile.lock | 7 ++++++- webapp/app.rb | 21 +++++++++++++++++++-- 4 files changed, 58 insertions(+), 8 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 923c0bd..11606f0 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,6 +2,18 @@ version: '3' services: webapp: - image: 'rtyler/codevalet-webapp:latest' + image: 'codevalet/webapp:latest' ports: - 9292:9292 + links: + - cache + environment: + - USE_MEMCACHED=true + - SESSION_SECRET=fiddlesticks + - WARDEN_GITHUB_VERIFIER_SECRET=fiddlesticks + + cache: + image: 'memcached:alpine' + command: '-v' + ports: + - 11211:11211 diff --git a/webapp/Gemfile b/webapp/Gemfile index 2f8b09c..f20f853 100644 --- a/webapp/Gemfile +++ b/webapp/Gemfile @@ -1,12 +1,28 @@ source 'https://rubygems.org' +# Web framework, yey gem 'sinatra' -gem 'haml' -gem 'warden-github' -gem 'kramdown' -gem 'sentry-raven' + +# The actual webserver gem 'puma' +# For rendering all the views +gem 'haml' + +# Provides some semblance of github-based authentication and authorization +# within the rack app +gem 'warden-github' + +# Responsible for markdown parsing in the webapp views +gem 'kramdown' + +# Send exceptions into Sentry from the app +gem 'sentry-raven' + +# For memcached access +gem 'dalli' +gem 'rack-cache' + group :test do gem 'rspec' end diff --git a/webapp/Gemfile.lock b/webapp/Gemfile.lock index bbb4fe6..42bbd7c 100644 --- a/webapp/Gemfile.lock +++ b/webapp/Gemfile.lock @@ -9,6 +9,7 @@ GEM addressable (2.5.1) public_suffix (~> 2.0, >= 2.0.2) concurrent-ruby (1.0.5) + dalli (2.7.6) diff-lcs (1.3) faraday (0.12.2) multipart-post (>= 1.2, < 3) @@ -25,6 +26,8 @@ GEM public_suffix (2.0.5) puma (3.10.0) rack (2.0.3) + rack-cache (1.7.1) + rack (>= 0.4) rack-protection (2.0.0) rack rspec (3.6.0) @@ -66,13 +69,15 @@ PLATFORMS ruby DEPENDENCIES + dalli haml kramdown puma + rack-cache rspec sentry-raven sinatra warden-github BUNDLED WITH - 1.15.3 + 1.16.0 diff --git a/webapp/app.rb b/webapp/app.rb index 1868b78..86bf4ed 100644 --- a/webapp/app.rb +++ b/webapp/app.rb @@ -1,9 +1,13 @@ #!/usr/bin/env ruby +require 'securerandom' +require 'yaml' + +require 'dalli' require 'haml' +require 'rack/session/dalli' require 'sinatra/base' require 'warden/github' -require 'yaml' Haml::TempleEngine.disable_option_validator! @@ -24,11 +28,24 @@ module CodeValet include Warden::GitHub::SSO enable :sessions + set :session_secret, ENV.fetch('SESSION_SECRET') { SecureRandom.hex(64) } + enable :raise_errors - disable :show_exceptions + + if ENV['PRODUCTION'] + disable :show_exceptions + end set :public_folder, File.dirname(__FILE__) + '/assets' + configure do + if ENV['PRODUCTION'] || ENV['USE_MEMCACHED'] + use Rack::Session::Dalli, + :namespace => 'webapp.sessions', + :cache => Dalli::Client.new(ENV.fetch('MEMCACHED_SERVER') { 'cache:11211' }) + end + end + use Warden::Manager do |config| config.failure_app = AuthFailre config.default_strategies :github From 1b8e86f237b8f60ee5e60e7799a73bb2c4f402e8 Mon Sep 17 00:00:00 2001 From: "R. Tyler Croy" Date: Sat, 23 Dec 2017 14:47:53 -0800 Subject: [PATCH 4/4] Deploy a memcached service for storing dataz With shared and predictable session storage, raise the replicas for the webapp a bit too --- k8s/20-webapp.yaml | 72 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 67 insertions(+), 5 deletions(-) diff --git a/k8s/20-webapp.yaml b/k8s/20-webapp.yaml index c3a4253..c402c2e 100644 --- a/k8s/20-webapp.yaml +++ b/k8s/20-webapp.yaml @@ -15,6 +15,7 @@ items: selector: app: 'webapp' + - apiVersion: extensions/v1beta1 kind: Deployment metadata: @@ -23,7 +24,7 @@ items: labels: name: 'webapp' spec: - replicas: 1 + replicas: 3 strategy: type: RollingUpdate selector: @@ -54,16 +55,23 @@ items: value: 'https://codevalet.io/github/authenticate' - name: GITHUB_CLIENT_ID value: '790a28783a813e2b2b3c' + - name: MEMCACHED_SERVER + value: 'memcached.webapp.svc.cluster.local' + - name: SESSION_SECRET + valueFrom: + secretKeyRef: + name: 'webapp' + key: 'sessionsecret' - name: SENTRY_DSN valueFrom: secretKeyRef: - name: webapp - key: sentry + name: 'webapp' + key: 'sentry' - name: GITHUB_CLIENT_SECRET valueFrom: secretKeyRef: - name: oauth - key: secret + name: 'oauth' + key: 'secret' livenessProbe: httpGet: path: / @@ -71,6 +79,60 @@ items: initialDelaySeconds: 60 timeoutSeconds: 10 + - apiVersion: extensions/v1beta1 + kind: Deployment + metadata: + name: 'memcached' + namespace: 'webapp' + labels: + name: 'memcached' + spec: + replicas: 3 + strategy: + type: RollingUpdate + selector: + template: + metadata: + labels: + app: 'memcached' + spec: + containers: + - name: 'cache' + image: 'memcached:alpine' + imagePullPolicy: Always + ports: + - containerPort: 11211 + name: 'memcached' + resources: + requests: + memory: 64M + limits: + memory: 256M + livenessProbe: + tcpSocket: + port: 'memcached' + initialDelaySeconds: 30 + timeoutSeconds: 5 + readinessProbe: + tcpSocket: + port: 'memcached' + initialDelaySeconds: 5 + timeoutSeconds: 1 + + - apiVersion: v1 + kind: Service + metadata: + name: 'memcached' + namespace: 'webapp' + spec: + clusterIP: None + ports: + - port: 11211 + targetPort: 'memcached' + protocol: TCP + selector: + app: 'memcached' + - apiVersion: extensions/v1beta1 kind: Ingress metadata: