From a8e7ec534ba1976bc2f289bc08bc87d13530cc1c Mon Sep 17 00:00:00 2001 From: "S. Brent Faulkner" Date: Sat, 17 Jun 2017 13:48:05 -0400 Subject: [PATCH] Add Ruby environment (#223) Adds a Ruby environment and examples. --- environments/ruby/Dockerfile | 16 ++++++++ environments/ruby/Gemfile | 4 ++ environments/ruby/Gemfile.lock | 13 +++++++ environments/ruby/README.md | 41 ++++++++++++++++++++ environments/ruby/server.rb | 66 ++++++++++++++++++++++++++++++++ examples/ruby/events_to_slack.rb | 33 ++++++++++++++++ examples/ruby/hello.rb | 4 ++ examples/ruby/request_data.rb | 19 +++++++++ 8 files changed, 196 insertions(+) create mode 100644 environments/ruby/Dockerfile create mode 100644 environments/ruby/Gemfile create mode 100644 environments/ruby/Gemfile.lock create mode 100644 environments/ruby/README.md create mode 100644 environments/ruby/server.rb create mode 100644 examples/ruby/events_to_slack.rb create mode 100644 examples/ruby/hello.rb create mode 100644 examples/ruby/request_data.rb diff --git a/environments/ruby/Dockerfile b/environments/ruby/Dockerfile new file mode 100644 index 00000000..778816a1 --- /dev/null +++ b/environments/ruby/Dockerfile @@ -0,0 +1,16 @@ +FROM ruby:2.4.1 + +RUN apt-get update -qq && apt-get install -y build-essential + +RUN mkdir /app +WORKDIR /app +ADD Gemfile /app/Gemfile +ADD Gemfile.lock /app/Gemfile.lock +RUN bundle install + +COPY . /app + +EXPOSE 8888 + +ENTRYPOINT ["ruby"] +CMD ["server.rb"] diff --git a/environments/ruby/Gemfile b/environments/ruby/Gemfile new file mode 100644 index 00000000..4b94f42d --- /dev/null +++ b/environments/ruby/Gemfile @@ -0,0 +1,4 @@ +# frozen_string_literal: true +source "https://rubygems.org" + +gem "rack" diff --git a/environments/ruby/Gemfile.lock b/environments/ruby/Gemfile.lock new file mode 100644 index 00000000..4f2a6532 --- /dev/null +++ b/environments/ruby/Gemfile.lock @@ -0,0 +1,13 @@ +GEM + remote: https://rubygems.org/ + specs: + rack (2.0.3) + +PLATFORMS + ruby + +DEPENDENCIES + rack + +BUNDLED WITH + 1.15.1 diff --git a/environments/ruby/README.md b/environments/ruby/README.md new file mode 100644 index 00000000..90b74a20 --- /dev/null +++ b/environments/ruby/README.md @@ -0,0 +1,41 @@ +# Fission: Ruby Environment + +This is the Ruby environment for Fission. + +It's a Docker image containing a Ruby 2.4.1 runtime, along with a +dynamic loader. A few common dependencies are included in the +Gemfile. + +## Customizing this image + +To add package dependencies, edit Gemfile to add what you +need, and rebuild this image (instructions below). + +## Rebuilding and pushing the image + +You'll need access to a Docker registry to push the image: you can +sign up for Docker hub at hub.docker.com, or use registries from +gcr.io, quay.io, etc. Let's assume you're using a docker hub account +called USER. Build and push the image to the the registry: + +``` + docker build -t USER/ruby-env . && docker push USER/ruby-env +``` + +## Using the image in fission + +You can add this customized image to fission with "fission env +create": + +``` + fission env create --name ruby --image USER/ruby-env +``` + +Or, if you already have an environment, you can update its image: + +``` + fission env update --name ruby --image USER/ruby-env +``` + +After this, fission functions that have the env parameter set to the +same environment name as this command will use this environment. diff --git a/environments/ruby/server.rb b/environments/ruby/server.rb new file mode 100644 index 00000000..8a00f32a --- /dev/null +++ b/environments/ruby/server.rb @@ -0,0 +1,66 @@ +# frozen_string_literal: true +require 'rack' + +CODEPATH = '/userfunc/user' + +module Fission + class Request < Rack::Request + def headers + Hash[ + *env.select { |k,v| k.start_with?('HTTP_') } + .map { |k,v| [k.sub(/\AHTTP_/, '').split('_').map(&:capitalize).join('-'), v] } + .sort + .flatten + ] + end + end + + class Context + attr_reader :env + + def initialize(env) + @env = env + end + + def request + @request ||= Request.new(env) + end + end + + module Specializer + def self.call(env) + load CODEPATH + Rack::Response.new([], 201).finish + rescue + Rack::Response.new(['500 Internal Server Error'], 500, {}).finish + end + end + + module Handler + def self.call(env) + response = if method(:handler).arity > 0 + handler(Context.new(env)) + else + handler + end + + response.is_a?(Array) ? response : Rack::Response.new([response]).finish + rescue + Rack::Response.new(['500 Internal Server Error'], 500, {}).finish + end + end +end + +app = Rack::Builder.new do + use Rack::CommonLogger, $stderr + + map "/specialize" do + run Fission::Specializer + end + + map "/" do + run Fission::Handler + end +end + +Rack::Handler::WEBrick.run app, Host: '0.0.0.0', Port: 8888 diff --git a/examples/ruby/events_to_slack.rb b/examples/ruby/events_to_slack.rb new file mode 100644 index 00000000..861ab50c --- /dev/null +++ b/examples/ruby/events_to_slack.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true +require 'net/http' +require 'uri' +require 'json' + +SLACK_BASE_URL = 'https://hooks.slack.com/' +SLACK_WEBHOOK_PATH = 'YOUR RELATIVE PATH HERE' # Something like "/services/XXX/YYY/zZz123" + +def send_slack_message(message) + uri = URI.join(SLACK_BASE_URL, SLACK_WEBHOOK_PATH) + data = "{'channel': '#hackdays-serverless', 'username': 'fissionbot', 'text': \"#{message}\", 'icon_emoji': ':fission:'}" + res = Net::HTTP.post_form(uri, payload: data) + res.success? +end + +def handler(context) + request = context.request + + event_type = request.headers['X-Kubernetes-Event-Type'] + object_type = request.headers['X-Kubernetes-Object-Type'] + + object = JSON.parse(request.body.read) + object_name = object.dig('metadata', 'name') + object_namespace = object.dig('metadata', 'namespace') + + message = "#{event_type} #{object_type} #{object_namespace}/#{object_name}" + + if send_slack_message(message) + "Slack message sent - #{message}" + else + Rack::Response.new(["Failed to send Slack message - #{message}"], 500).finish + end +end diff --git a/examples/ruby/hello.rb b/examples/ruby/hello.rb new file mode 100644 index 00000000..75e4c88a --- /dev/null +++ b/examples/ruby/hello.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true +def handler + "Hello, world!\n" +end diff --git a/examples/ruby/request_data.rb b/examples/ruby/request_data.rb new file mode 100644 index 00000000..cc17b283 --- /dev/null +++ b/examples/ruby/request_data.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true +def handler(context) + request = context.request + msg = <<~MSG + ---ENV--- + #{request.env.map { |h| h.join('=') }.join("\n") } + + ---HEADERS--- + #{request.headers.map { |h| h.join(': ') }.join("\n") } + + ---PARAMS--- + #{request.params.map { |h| h.join('=') }.join("\n") } + + --BODY-- + #{request.body.read} + MSG + + Rack::Response.new([msg]).finish +end