#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'
set -vx

bundle install

# Prepariamo l'applicazione esempio
rm -fr spec/dummy
bundle exec rails new spec/dummy --skip-git --skip-javascript --skip-hotwire --skip-jbuilder --skip-test --skip-bootsnap --force

echo "Changes to application"

sed -i 's/"2.7.4"/">= 2.7.4"/' spec/dummy/Gemfile
sed -i '/end/i root "main#index"' spec/dummy/config/routes.rb
sed -i '/root "main#index"/i get  "create_job", to:  "main#create_job", as: "create_job"' spec/dummy/config/routes.rb

echo '
class MainController < ApplicationController
  include ActionView::Helpers::UrlHelper
  def index
    render inline: "#{link_to HelloWorldJob.name,create_job_path}"
  end

  def create_job
    HelloWorldJob.perform_later
    redirect_to root_path
  end

end
' > spec/dummy/app/controllers/main_controller.rb

echo '
Rails.application.configure do

  auth_options = {
    bearer_token_file: "/var/run/secrets/kubernetes.io/serviceaccount/token"
  }
  ssl_options = {}
  if File.exist?("/var/run/secrets/kubernetes.io/serviceaccount/ca.crt")
    ssl_options[:ca_file] = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
  end
  api_endpoint = "https://kubernetes.default.svc"
  api_version = "v1"
  namespace = File.read("/var/run/secrets/kubernetes.io/serviceaccount/namespace")

  context = Kubeclient::Config::Context.new(
    api_endpoint,
    api_version,
    ssl_options,
    auth_options,
    namespace
  )

  config.active_job.queue_adapter = ActiveJob::QueueAdapters::K8sAdapter.new(
    kubeclient_context: context
  )

end
' > spec/dummy/config/initializers/active_job_k8s.rb

echo '
class HelloWorldJob < ApplicationJob
  queue_as :default

  def perform(*args)
    Rails.logger.debug "Hello World"
    FileUtils.touch(Rails.root.join("tmp","#{SecureRandom.hex}.test"))
  end

  def manifest
    YAML.safe_load(
      <<~MANIFEST
          apiVersion: batch/v1
          kind: Job
          metadata:
            name: scheduled-job-name
            namespace: default
          spec:
            template:
              spec:
                restartPolicy: Never
                containers:
                - name: app-job
                  image: activejobk8s:0.1.0
                  imagePullPolicy: IfNotPresent
                  env:
                    - name: RAILS_SERVE_STATIC_FILES
                      value: "1"
                    - name: RAILS_LOG_TO_STDOUT
                      value: "1"
                    - name: RAILS_ENV
                      value: "development"
                  command: ["/bin/sh"]
                  args:
                    - "-ec"
                    - "bundle install && bundle exec rails active_job_k8s:run_job"
                  volumeMounts:
                  - mountPath: /usr/src/app
                    name: application-volume
                volumes:
                - name: application-volume
                  hostPath:
                    # directory location on host
                    path: /application

    MANIFEST
    )
  end
end
' > spec/dummy/app/jobs/hello_world_job.rb

echo 'FROM ruby:3.0.4-alpine3.16

RUN apk update \
    && apk upgrade \
    && apk add --update alpine-conf bash tzdata build-base curl-dev curl git yaml-dev zlib-dev

RUN gem install bundler:2.3.7

# throw errors if Gemfile has been modified since Gemfile.lock
WORKDIR /usr/src/app/spec/dummy

COPY Gemfile Gemfile.lock ./
RUN bundle install

COPY . .

CMD ["/bin/sh", "-ec", "bundle install && bundle exec rails s -b 0.0.0.0 -p 3000"]' > spec/dummy/Dockerfile

docker build -t activejobk8s:0.1.0 spec/dummy/.

# aggiungiamo la path ad active_job_k8s nel Gemfile che viene poi usato nel cluster e che punta alla gemma.
echo "gem 'active_job_k8s', path:'/usr/src/app' " >> spec/dummy/Gemfile


echo "START KIND ENV"
kind delete cluster -n active-job-cluster
kind create cluster --config bin/cluster.yaml
kubectl config set-context active-job-cluster

echo "SLEEP for cluster to be ready"
sleep 10

kind load docker-image activejobk8s:0.1.0 -n active-job-cluster

kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: test-activejobk8s
  namespace: default
  labels:
    app: active-job-app
spec:
  containers:
  - name: app
    image: activejobk8s:0.1.0
    imagePullPolicy: Never
    ports:
      - name: app
        containerPort: 3000
        protocol: TCP
    env:
      - name: RAILS_SERVE_STATIC_FILES
        value: '1'
      - name: RAILS_LOG_TO_STDOUT
        value: '1'
      - name: RAILS_ENV
        value: 'development'
    volumeMounts:
    - mountPath: /usr/src/app
      name: application-volume
  volumes:
  - name: application-volume
    hostPath:
      # directory location on host
      path: /application
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: jobs-edit
  namespace: default
rules:
  - apiGroups:
      - "batch"
    resources:
      - jobs
    verbs:
      - get
      - list
      - watch
      - create
      - delete
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: jobs-edit
  namespace: default
subjects:
  - kind: ServiceAccount
    name: default
    namespace: default
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: jobs-edit
---
apiVersion: v1
kind: Service
metadata:
  name: app-service
  namespace: default
  labels:
    app: app-service
spec:
  ports:
    - name: 3000-3000
      protocol: TCP
      port: 3000
      targetPort: 3000
      nodePort: 30335
  selector:
    app: active-job-app
  type: NodePort
EOF

echo "Open browser to 0.0.0.0:3000"
open http://0.0.0.0:3000
