module Builder

Public Class Methods

create_dockerfile() click to toggle source
# File lib/citasks/ci_lib.rb, line 481
  def self.create_dockerfile
    File.open "Dockerfile", "w" do |fh|
      fh.puts <<~EOF
        FROM alpine
        ADD myhandler /
        RUN chmod a+rx /myhandler
        ENV LISTENING_PORT 80

        CMD ["/myhandler"]
      EOF
    end
  end
create_env(app_name) click to toggle source
# File lib/citasks/ci_lib.rb, line 301
  def self.create_env app_name
    _write ".env.build", <<~EOF
      IMAGE_NAME=#{app_name}

      PRIVATE_DOCKER_REGISTRY_NAME=#{ENV["ICP_REGISTRY_HOSTNAME"]}
      PRIVATE_DOCKER_REGISTRY_PORT=8500
      PRIVATE_DOCKER_REGISTRY_IP=#{ENV["ICP_MASTER_IP"]}
      PRIVATE_DOCKER_REGISTRY_NAMESPACE=#{ENV["PRIVATE_DOCKER_REGISTRY_NAMESPACE"]}

      PRIVATE_DOCKER_REGISTRY_USER=admin
      PRIVATE_DOCKER_REGISTRY_USER_PASSWORD=admin

      PRIVATE_DOCKER_REGISTRY_PULL_SECRET=#{ENV["IMAGE_PULL_SECRET"]}

      K8S_NAMESPACE=#{ENV["K8S_NAMESPACE"]}
    EOF
  end
create_k8_file(namespace, app_name, pull_secret=ENV["IMAGE_PULL_SECRET"]) click to toggle source
# File lib/citasks/ci_lib.rb, line 494
  def self.create_k8_file namespace, app_name, pull_secret=ENV["IMAGE_PULL_SECRET"]
    _write "#{app_name}.k8.template.yaml", <<~EOF
      apiVersion: extensions/v1beta1
      kind: Deployment
      metadata:
        namespace: #{namespace}
        name: #{app_name}
        labels:
          app: #{app_name}
          type: jenkins-build
      spec:
        replicas: 2
        template:
          metadata:
            labels:
              app: #{app_name}
          spec:
            containers:
            - name: #{app_name}
              image: <%= new_image %>
            imagePullSecrets:
            - name: #{pull_secret}
      ---
      apiVersion: v1
      kind: Service
      metadata:
        namespace: #{namespace}
        name: #{app_name}
        labels:
          app: #{app_name}
      spec:
        type: NodePort
        ports:
          - port: 80
            targetPort: 80
            protocol: TCP
            name: http
        selector:
          app: #{app_name}
      ---
      apiVersion: extensions/v1beta1
      kind: Ingress
      metadata:
        namespace: #{namespace}
        name: #{app_name}-ingress
        labels:
          app: #{app_name}-ingress
      spec:
        rules:
          - host: k8s.myvm.io
            http:
              paths:
                - path: /
                  backend:
                    serviceName: #{app_name}
                    servicePort: http
    EOF
  end
create_lib_files() click to toggle source
# File lib/citasks/ci_lib.rb, line 319
  def self.create_lib_files
    FileUtils.mkdir_p lib_dir = "build_libs"

    _write lib_dir + "/helpers.rb", <<~EOF
      require "yaml"

      require_relative "docker.rb"
      require_relative "k8s.rb"

      @task_index=0
      def next_task_index
        @task_index += 1
        sprintf("%02d", @task_index)
      end

      def reset_task_index
        @task_index = 0
      end
    EOF

    _write lib_dir + "/shell.rb", <<~EOF
      module ShellCommandConstructor
        def self.construct_command strings_or_list, connector = " && "
          list = case strings_or_list
          when Array
            strings_or_list
          when String
            strings_or_list.split(/\\n/)
          end
          list.each_with_object([]) do |line, obj|
              line.strip!
              next if line.empty?
              next if line =~ /^#/
              obj.push line
          end.join connector
        end
      end

      module Shell
        def self.run cmd
          unless system(cmd)
            fail "Failed to execute \#{cmd}"
          end
        end

        def self.test cmd
          system cmd
        end
      end
    EOF

    _write lib_dir + "/docker.rb", <<~EOF
      require_relative "shell"

      module DockerTools
        def self.add_etc_hosts
          etc_hosts_entry = sprintf("%s %s", ENV["PRIVATE_DOCKER_REGISTRY_IP"], ENV["PRIVATE_DOCKER_REGISTRY_NAME"])
          Shell.run %Q(echo "\#{etc_hosts_entry}" >> /etc/hosts)
        end

        def self.push_to_registry image_name, tag
          private_registry = sprintf("%s:%s", ENV["PRIVATE_DOCKER_REGISTRY_NAME"], ENV["PRIVATE_DOCKER_REGISTRY_PORT"])
          namespace = ENV["PRIVATE_DOCKER_REGISTRY_NAMESPACE"]

          cmds = ShellCommandConstructor.construct_command %Q{
            docker login -u \#{ENV["PRIVATE_DOCKER_REGISTRY_USER"]} -p \#{ENV["PRIVATE_DOCKER_REGISTRY_USER_PASSWORD"]} \#{private_registry}

            docker tag \#{image_name}:\#{tag} \#{private_registry}/\#{namespace}/\#{image_name}:\#{tag}
            docker push \#{private_registry}/\#{namespace}/\#{image_name}:\#{tag}
          }
          Shell.run cmds
        end
      end
    EOF

    _write lib_dir + '/k8s.rb', <<~EOF
      require "erb"
      require_relative "shell"

      module KubeTools
        def self.create_namespace namespace
          Shell.run %Q(kubectl create namespace \#{namespace} || echo ignore exists error)
        end

        def self.create_pull_secret namespace, user, pass, secret_name
          Shell.run %Q(kubectl delete secret \#{secret_name} -n \#{namespace} || echo ignore non exists error)
          Shell.run %Q(kubectl create secret docker-registry \#{secret_name} -n \#{namespace} --docker-server=\#{ENV["PRIVATE_DOCKER_REGISTRY_NAME"]}:\#{ENV["PRIVATE_DOCKER_REGISTRY_PORT"]} --docker-username=\#{ENV["PRIVATE_DOCKER_REGISTRY_USER"]} --docker-password=\#{ENV["PRIVATE_DOCKER_REGISTRY_USER_PASSWORD"]} --docker-email=\#{ENV["PRIVATE_DOCKER_REGISTRY_USER"]}@\#{ENV["PRIVATE_DOCKER_REGISTRY_NAME"]})
        end


        def self.create_new_yaml yaml_template_file, yaml_file, data = {}
          erb = ERB.new(File.read(yaml_template_file))
          b = binding

          data.each_pair do |key, value|
            b.local_variable_set(key, value)
          end

          File.open yaml_file, "w" do |fh|
            fh.puts erb.result(b)
          end
        end

        def self.deploy_to_k8s yaml_file
          Shell.run %Q(kubectl apply -f \#{yaml_file})
        end
      end
    EOF

  end
create_rakefile() click to toggle source
# File lib/citasks/ci_lib.rb, line 430
  def self.create_rakefile
    _write "build.rb", <<~OUTEOF
      require 'dotenv'
      Dotenv.load ".env.build"
      require_relative "build_libs/helpers"

      image_name = ENV["IMAGE_NAME"]
      tag=ENV["BUILD_NUMBER"]||"B1"

      namespace "docker" do
        reset_task_index

        desc "build docker image"
        task "\#{next_task_index}_build_image" do
          sh %Q(docker build -t \#{image_name}:\#{tag} .)
        end

        desc "push to ICp registry"
        task "\#{next_task_index}_push_to_ICp_registry" do
          DockerTools.add_etc_hosts
          KubeTools.create_namespace ENV["K8S_NAMESPACE"]
          DockerTools.push_to_registry image_name, tag
        end
      end

      namespace "k8s" do
        reset_task_index

        desc "deploy into k8s"
        task "\#{next_task_index}_deploy_to_k8s" do
          KubeTools.create_pull_secret ENV["K8S_NAMESPACE"], ENV["PRIVATE_DOCKER_REGISTRY_USER"], ENV["PRIVATE_DOCKER_REGISTRY_USER_PASSWORD"], ENV["PRIVATE_DOCKER_REGISTRY_PULL_SECRET"]

          yaml_template_file = "\#{image_name}.k8.template.yaml"
          yaml_file = "\#{image_name}.yaml"

          private_registry = sprintf("%s:%s", ENV["PRIVATE_DOCKER_REGISTRY_NAME"], ENV["PRIVATE_DOCKER_REGISTRY_PORT"])
          namespace = ENV["PRIVATE_DOCKER_REGISTRY_NAMESPACE"]

          full_new_image_name = "\#{private_registry}/\#{namespace}/\#{image_name}:\#{tag}"
          data = {
            new_image: full_new_image_name
          }

          KubeTools.create_new_yaml yaml_template_file, yaml_file, data

          KubeTools.deploy_to_k8s yaml_file
        end
      end
    OUTEOF
  end