cuber 0.0.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +86 -0
- data/SSAL-LICENSE +9 -0
- data/bin/cuber +3 -0
- data/cuber.gemspec +13 -0
- data/lib/cuber/cli.rb +55 -0
- data/lib/cuber/commands/deploy.rb +101 -0
- data/lib/cuber/commands/info.rb +134 -0
- data/lib/cuber/commands/logs.rb +18 -0
- data/lib/cuber/commands/restart.rb +14 -0
- data/lib/cuber/commands/run.rb +48 -0
- data/lib/cuber/commands/version.rb +13 -0
- data/lib/cuber/cuberfile_parser.rb +91 -0
- data/lib/cuber/cuberfile_validator.rb +146 -0
- data/lib/cuber/templates/deployment.yml.erb +332 -0
- data/lib/cuber/templates/pod.yml.erb +22 -0
- data/lib/cuber/utils.rb +24 -0
- data/lib/cuber/version.rb +3 -0
- data/lib/cuber.rb +15 -0
- metadata +43 -9
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 26ed60418289b2d4b6e39d87691661c9c5d9c57cac883d4d21a224d7e7fc7271
         | 
| 4 | 
            +
              data.tar.gz: c4093343c2fac80c5adabba7cfe285e60e30fc722d4dbb01e24df840144bbbbf
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 168df66b846819cda138affc0bdbbd95185815367aeaadc210ef215404b514239ed812ed2f18885255c9909a1a3345e4819b96709fd2387e5586c6037025327c
         | 
| 7 | 
            +
              data.tar.gz: ea4fffbab3fd2c3ba50d2ff587a029472ea826fad9deb33c95190b54c331ca97ea1f1cbafb1e4fc5c4627540bcfc256c6b00e31286087879df366701ca76df41
         | 
    
        data/README.md
    ADDED
    
    | @@ -0,0 +1,86 @@ | |
| 1 | 
            +
            <a href="https://cuber.cloud"><img src="https://cuber.cloud/assets/images/logo.svg" alt="Cuber" height="80" width="80"></a>
         | 
| 2 | 
            +
              
         | 
| 3 | 
            +
            # CUBER
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            [](https://badge.fury.io/rb/cuber)
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            Deploy your apps on Kubernetes easily.
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            ## What is Cuber?
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            Cuber is an automation tool (written in Ruby) that can package and deploy your apps (written in any language and framework) on Kubernetes.
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            Unlike other tools that add more options and more complexity to Kubernetes, Cuber is made to simplify and reduce the complexity.
         | 
| 14 | 
            +
            You just need to create a `Cuberfile`, with ~10 lines of code, and then type `cuber deploy` to package and deploy your app on any Kubernetes cluster.
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            Kubernetes is up to 80% cheaper compared to PaaS like Heroku and you can choose between different cloud providers (no lock-in).
         | 
| 17 | 
            +
            It is also reliable and it can scale enterprise applications at any size.
         | 
| 18 | 
            +
            The only downside is that it's difficult to master...
         | 
| 19 | 
            +
            Cuber makes Kubernetes simple!
         | 
| 20 | 
            +
            In this way you have the simplicity of a PaaS, at the cost of bare infrastructure and without the additional cost of a DevOps team.
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            [Read more](https://cuber.cloud/docs/overview)
         | 
| 23 | 
            +
             | 
| 24 | 
            +
            ## Installation
         | 
| 25 | 
            +
             | 
| 26 | 
            +
            First you need to [install the prerequisites](https://cuber.cloud/docs/installation): `ruby`, `git`, `docker`, `pack`, `kubectl`.
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            Then install Cuber:
         | 
| 29 | 
            +
             | 
| 30 | 
            +
            ```
         | 
| 31 | 
            +
            $ gem install cuber
         | 
| 32 | 
            +
            ```
         | 
| 33 | 
            +
             | 
| 34 | 
            +
            ## Quickstart
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            Open your application folder and create a `Cuberfile`, for example:
         | 
| 37 | 
            +
             | 
| 38 | 
            +
            ```ruby
         | 
| 39 | 
            +
            # Give a name to your app
         | 
| 40 | 
            +
            app 'myapp'
         | 
| 41 | 
            +
             | 
| 42 | 
            +
            # Get the code from this Git repository
         | 
| 43 | 
            +
            repo '.'
         | 
| 44 | 
            +
             | 
| 45 | 
            +
            # Build the Docker image automatically (or provide a Dockerfile)
         | 
| 46 | 
            +
            buildpacks 'heroku/buildpacks:20'
         | 
| 47 | 
            +
             | 
| 48 | 
            +
            # Publish the Docker image in a registry
         | 
| 49 | 
            +
            image 'username/myapp'
         | 
| 50 | 
            +
             | 
| 51 | 
            +
            # Connect to this Kubernetes cluster
         | 
| 52 | 
            +
            kubeconfig 'path/to/kubeconfig.yml'
         | 
| 53 | 
            +
             | 
| 54 | 
            +
            # Run and scale any command on Kubernetes
         | 
| 55 | 
            +
            proc :web, 'your web server command'
         | 
| 56 | 
            +
            ```
         | 
| 57 | 
            +
             | 
| 58 | 
            +
            You can also see [a more complete example](https://cuber.cloud/docs/quickstart).
         | 
| 59 | 
            +
             | 
| 60 | 
            +
            Then in your terminal:
         | 
| 61 | 
            +
             | 
| 62 | 
            +
            ```
         | 
| 63 | 
            +
            $ cuber deploy
         | 
| 64 | 
            +
            ```
         | 
| 65 | 
            +
             | 
| 66 | 
            +
            Finally you can also monitor the status of your application:
         | 
| 67 | 
            +
             | 
| 68 | 
            +
            ```
         | 
| 69 | 
            +
            $ cuber info
         | 
| 70 | 
            +
            ```
         | 
| 71 | 
            +
             | 
| 72 | 
            +
            Check out the [Cuberfile configuration](https://cuber.cloud/docs/cuberfile) and the [Cuber CLI commands](https://cuber.cloud/docs/cli) for more information.
         | 
| 73 | 
            +
             | 
| 74 | 
            +
            ## License
         | 
| 75 | 
            +
             | 
| 76 | 
            +
            Cuber is released under a source-available license:
         | 
| 77 | 
            +
            [Standard Source Available License (SSAL)](https://github.com/collimarco/Standard-Source-Available-License)
         | 
| 78 | 
            +
             | 
| 79 | 
            +
            Cuber is completely free up to 5 procs per app (and you can publish unlimited apps). If you are a large customer, and you need more procs to scale your applications, please [purchase a license](https://cuber.cloud/buy) (it also includes dedicated support).
         | 
| 80 | 
            +
             | 
| 81 | 
            +
            Contributions are welcome: you can fork this project on GitHub and submit a pull request. If you submit a change / fix, we can use it without restrictions and you transfer the copyright of your contribution to Cuber.
         | 
| 82 | 
            +
             | 
| 83 | 
            +
            ## Learn more
         | 
| 84 | 
            +
             | 
| 85 | 
            +
            You can find more information and documentation on [cuber.cloud →](https://cuber.cloud)
         | 
| 86 | 
            +
             | 
    
        data/SSAL-LICENSE
    ADDED
    
    | @@ -0,0 +1,9 @@ | |
| 1 | 
            +
            Copyright 2022 Cuber (AbstractBrain srls)
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            Use and modifications are permitted under the following conditions:
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            1. The above copyright notice and this permission must be retained in all copies.
         | 
| 6 | 
            +
            2. The modifications to the software must not circumvent license key validations or other license-related code.
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED.
         | 
| 9 | 
            +
            IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY.
         | 
    
        data/bin/cuber
    ADDED
    
    
    
        data/cuber.gemspec
    ADDED
    
    | @@ -0,0 +1,13 @@ | |
| 1 | 
            +
            require_relative 'lib/cuber/version'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            Gem::Specification.new do |s|
         | 
| 4 | 
            +
              s.name = 'cuber'
         | 
| 5 | 
            +
              s.version = Cuber::VERSION
         | 
| 6 | 
            +
              s.summary = 'Deploy your apps on Kubernetes easily.'
         | 
| 7 | 
            +
              s.author = 'Cuber'
         | 
| 8 | 
            +
              s.homepage = 'https://cuber.cloud'
         | 
| 9 | 
            +
              s.license = 'LicenseRef-SSAL-LICENSE'
         | 
| 10 | 
            +
              s.executables = ['cuber']
         | 
| 11 | 
            +
              s.files = `git ls-files`.split("\n")
         | 
| 12 | 
            +
              s.add_dependency 'jwt', '~> 2.3.0'
         | 
| 13 | 
            +
            end
         | 
    
        data/lib/cuber/cli.rb
    ADDED
    
    | @@ -0,0 +1,55 @@ | |
| 1 | 
            +
            require 'optparse'
         | 
| 2 | 
            +
            require 'fileutils'
         | 
| 3 | 
            +
            require 'open3'
         | 
| 4 | 
            +
            require 'erb'
         | 
| 5 | 
            +
            require 'base64'
         | 
| 6 | 
            +
            require 'yaml'
         | 
| 7 | 
            +
            require 'json'
         | 
| 8 | 
            +
            require 'shellwords'
         | 
| 9 | 
            +
            require 'time'
         | 
| 10 | 
            +
            require 'openssl'
         | 
| 11 | 
            +
            require 'jwt'
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            module Cuber
         | 
| 14 | 
            +
              class CLI
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                def initialize
         | 
| 17 | 
            +
                  @options = {}
         | 
| 18 | 
            +
                  parse_command!
         | 
| 19 | 
            +
                  parse_cuberfile
         | 
| 20 | 
            +
                  validate_cuberfile
         | 
| 21 | 
            +
                  execute
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                private
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                def parse_command!
         | 
| 27 | 
            +
                  @options[:cmd] = ARGV.shift&.to_sym
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                def parse_cuberfile
         | 
| 31 | 
            +
                  abort 'Cuberfile not found in current directory' unless File.exists? 'Cuberfile'
         | 
| 32 | 
            +
                  content = File.read 'Cuberfile'
         | 
| 33 | 
            +
                  parser = CuberfileParser.new
         | 
| 34 | 
            +
                  parser.instance_eval(content)
         | 
| 35 | 
            +
                  cuberfile_options = parser.instance_variables.map do |name|
         | 
| 36 | 
            +
                    [name[1..-1].to_sym, parser.instance_variable_get(name)]
         | 
| 37 | 
            +
                  end.to_h
         | 
| 38 | 
            +
                  @options.merge! cuberfile_options
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                def validate_cuberfile
         | 
| 42 | 
            +
                  validator = CuberfileValidator.new @options
         | 
| 43 | 
            +
                  errors = validator.validate
         | 
| 44 | 
            +
                  errors.each { |err| $stderr.puts "Cuberfile: #{err}" }
         | 
| 45 | 
            +
                  abort unless errors.empty?
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                def execute
         | 
| 49 | 
            +
                  command_class = @options[:cmd]&.capitalize
         | 
| 50 | 
            +
                  abort "Cuber: \"#{@options[:cmd]}\" is not a command" unless command_class && Cuber::Commands.const_defined?(command_class)
         | 
| 51 | 
            +
                  Cuber::Commands.const_get(command_class).new(@options).execute
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
              end
         | 
| 55 | 
            +
            end
         | 
| @@ -0,0 +1,101 @@ | |
| 1 | 
            +
            module Cuber::Commands
         | 
| 2 | 
            +
              class Deploy
         | 
| 3 | 
            +
                include Cuber::Utils
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                def initialize options
         | 
| 6 | 
            +
                  @options = options
         | 
| 7 | 
            +
                end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                def execute
         | 
| 10 | 
            +
                  if @options[:release]
         | 
| 11 | 
            +
                    print_step 'Deploying a past release'
         | 
| 12 | 
            +
                  else
         | 
| 13 | 
            +
                    checkout
         | 
| 14 | 
            +
                    set_release_name
         | 
| 15 | 
            +
                    if @options[:buildpacks]
         | 
| 16 | 
            +
                      pack
         | 
| 17 | 
            +
                    else
         | 
| 18 | 
            +
                      build
         | 
| 19 | 
            +
                      push
         | 
| 20 | 
            +
                    end
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
                  configure
         | 
| 23 | 
            +
                  apply
         | 
| 24 | 
            +
                  rollout
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                private
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                def print_step desc
         | 
| 30 | 
            +
                  puts
         | 
| 31 | 
            +
                  puts "\e[34m-----> #{desc}\e[0m"
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                def checkout
         | 
| 35 | 
            +
                  print_step 'Cloning Git repository'
         | 
| 36 | 
            +
                  path = '.cuber/repo'
         | 
| 37 | 
            +
                  FileUtils.mkdir_p path
         | 
| 38 | 
            +
                  FileUtils.rm_rf path, secure: true
         | 
| 39 | 
            +
                  cmd = ['git', 'clone']
         | 
| 40 | 
            +
                  cmd += ['--branch', @options[:repo][:branch]] if @options[:repo][:branch]
         | 
| 41 | 
            +
                  cmd += ['--depth', '1', @options[:repo][:url], path]
         | 
| 42 | 
            +
                  system(*cmd) || abort('Cuber: git clone failed')
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                def commit_hash
         | 
| 46 | 
            +
                  out, status = Open3.capture2 'git', 'rev-parse', '--short', 'HEAD', chdir: '.cuber/repo'
         | 
| 47 | 
            +
                  abort 'Cuber: cannot get commit hash' unless status.success?
         | 
| 48 | 
            +
                  out.strip
         | 
| 49 | 
            +
                end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                def set_release_name
         | 
| 52 | 
            +
                  @options[:release] = "#{commit_hash}-#{Time.now.utc.iso8601.delete('^0-9')}"
         | 
| 53 | 
            +
                end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                def pack
         | 
| 56 | 
            +
                  print_step 'Building image using buildpacks'
         | 
| 57 | 
            +
                  tag = "#{@options[:image]}:#{@options[:release]}"
         | 
| 58 | 
            +
                  cmd = ['pack', 'build', tag, '--builder', @options[:buildpacks], '--publish']
         | 
| 59 | 
            +
                  cmd += ['--pull-policy', 'always', '--clear-cache'] if @options[:cache] == false
         | 
| 60 | 
            +
                  system(*cmd, chdir: '.cuber/repo') || abort('Cuber: pack build failed')
         | 
| 61 | 
            +
                end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                def build
         | 
| 64 | 
            +
                  print_step 'Building image from Dockerfile'
         | 
| 65 | 
            +
                  dockerfile = @options[:dockerfile] || 'Dockerfile'
         | 
| 66 | 
            +
                  tag = "#{@options[:image]}:#{@options[:release]}"
         | 
| 67 | 
            +
                  cmd = ['docker', 'build']
         | 
| 68 | 
            +
                  cmd += ['--pull', '--no-cache'] if @options[:cache] == false
         | 
| 69 | 
            +
                  cmd += ['--platform', 'linux/amd64', '--progress', 'plain', '-f', dockerfile, '-t', tag, '.']
         | 
| 70 | 
            +
                  system(*cmd, chdir: '.cuber/repo') || abort('Cuber: docker build failed')
         | 
| 71 | 
            +
                end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                def push
         | 
| 74 | 
            +
                  print_step 'Pushing image to Docker registry'
         | 
| 75 | 
            +
                  tag = "#{@options[:image]}:#{@options[:release]}"
         | 
| 76 | 
            +
                  system('docker', 'push', tag) || abort('Cuber: docker push failed')
         | 
| 77 | 
            +
                end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                def configure
         | 
| 80 | 
            +
                  print_step 'Generating Kubernetes configuration'
         | 
| 81 | 
            +
                  @options[:instance] = "#{@options[:app]}-#{Time.now.utc.iso8601.delete('^0-9')}"
         | 
| 82 | 
            +
                  @options[:dockerconfigjson] = Base64.strict_encode64 File.read File.expand_path(@options[:dockerconfig] || '~/.docker/config.json')
         | 
| 83 | 
            +
                  render 'deployment.yml', '.cuber/kubernetes/deployment.yml'
         | 
| 84 | 
            +
                end
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                def apply
         | 
| 87 | 
            +
                  print_step 'Applying configuration to Kubernetes cluster'
         | 
| 88 | 
            +
                  kubectl 'apply',
         | 
| 89 | 
            +
                    '-f', '.cuber/kubernetes/deployment.yml',
         | 
| 90 | 
            +
                    '--prune', '-l', "app.kubernetes.io/name=#{@options[:app]},app.kubernetes.io/managed-by=cuber"
         | 
| 91 | 
            +
                end
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                def rollout
         | 
| 94 | 
            +
                  print_step 'Verifying deployment status'
         | 
| 95 | 
            +
                  @options[:procs].each_key do |procname|
         | 
| 96 | 
            +
                    kubectl 'rollout', 'status', "deployment/#{procname}"
         | 
| 97 | 
            +
                  end
         | 
| 98 | 
            +
                end
         | 
| 99 | 
            +
             | 
| 100 | 
            +
              end
         | 
| 101 | 
            +
            end
         | 
| @@ -0,0 +1,134 @@ | |
| 1 | 
            +
            module Cuber::Commands
         | 
| 2 | 
            +
              class Info
         | 
| 3 | 
            +
                include Cuber::Utils
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                def initialize options
         | 
| 6 | 
            +
                  @options = options
         | 
| 7 | 
            +
                  @namespace = nil
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                def execute
         | 
| 11 | 
            +
                  set_namespace
         | 
| 12 | 
            +
                  print_app_version
         | 
| 13 | 
            +
                  print_public_ip
         | 
| 14 | 
            +
                  print_env
         | 
| 15 | 
            +
                  print_migration
         | 
| 16 | 
            +
                  print_proc
         | 
| 17 | 
            +
                  print_cron
         | 
| 18 | 
            +
                  print_pods
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                private
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                def set_namespace
         | 
| 24 | 
            +
                  @namespace = kubeget 'namespace', @options[:app]
         | 
| 25 | 
            +
                  abort 'Cuber: app not found' if @namespace.dig('metadata', 'labels', 'app.kubernetes.io/managed-by') != 'cuber'
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                def print_section title
         | 
| 29 | 
            +
                  puts
         | 
| 30 | 
            +
                  puts "\e[34m=== #{title}\e[0m"
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                def print_app_version
         | 
| 34 | 
            +
                  print_section 'App'
         | 
| 35 | 
            +
                  puts "#{@namespace['metadata']['labels']['app.kubernetes.io/name']}"
         | 
| 36 | 
            +
                  puts "version #{@namespace['metadata']['labels']['app.kubernetes.io/version']}"
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                def print_public_ip
         | 
| 40 | 
            +
                  print_section 'Public IP'
         | 
| 41 | 
            +
                  if @namespace['metadata']['annotations']['ingress'] == 'true'
         | 
| 42 | 
            +
                    json = kubeget 'ingress', 'web-ingress'
         | 
| 43 | 
            +
                  else
         | 
| 44 | 
            +
                    json = kubeget 'service', 'load-balancer'
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
                  ip = json.dig 'status', 'loadBalancer', 'ingress', 0, 'ip'
         | 
| 47 | 
            +
                  if ip
         | 
| 48 | 
            +
                    puts "#{ip}"
         | 
| 49 | 
            +
                  else
         | 
| 50 | 
            +
                    puts "None detected"
         | 
| 51 | 
            +
                  end
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                def print_env
         | 
| 55 | 
            +
                  print_section 'Env'
         | 
| 56 | 
            +
                  json = kubeget 'configmap', 'env'
         | 
| 57 | 
            +
                  json['data']&.each do |key, value|
         | 
| 58 | 
            +
                    puts "#{key}=#{value}"
         | 
| 59 | 
            +
                  end
         | 
| 60 | 
            +
                  json = kubeget 'secrets', 'app-secrets'
         | 
| 61 | 
            +
                  json['data']&.each do |key, value|
         | 
| 62 | 
            +
                    puts "#{key}=#{Base64.decode64(value)[0...5] + '***'}"
         | 
| 63 | 
            +
                  end
         | 
| 64 | 
            +
                end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                def print_migration
         | 
| 67 | 
            +
                  print_section 'Migration'
         | 
| 68 | 
            +
                  migration = "migrate-#{@namespace['metadata']['labels']['app.kubernetes.io/instance']}"
         | 
| 69 | 
            +
                  json = kubeget 'job', migration, '--ignore-not-found'
         | 
| 70 | 
            +
                  if json
         | 
| 71 | 
            +
                    migration_command = json['spec']['template']['spec']['containers'][0]['command'].shelljoin
         | 
| 72 | 
            +
                    migration_status = json['status']['succeeded'].to_i.zero? ? 'Pending' : 'Completed'
         | 
| 73 | 
            +
                    puts "migrate: #{migration_command} (#{migration_status})"
         | 
| 74 | 
            +
                  else
         | 
| 75 | 
            +
                    puts "None detected"
         | 
| 76 | 
            +
                  end
         | 
| 77 | 
            +
                end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                def print_proc
         | 
| 80 | 
            +
                  print_section 'Proc'
         | 
| 81 | 
            +
                  json = kubeget 'deployments'
         | 
| 82 | 
            +
                  json['items'].each do |proc|
         | 
| 83 | 
            +
                    name = proc['metadata']['name']
         | 
| 84 | 
            +
                    command = proc['spec']['template']['spec']['containers'][0]['command'].shelljoin
         | 
| 85 | 
            +
                    available = proc['status']['availableReplicas'].to_i
         | 
| 86 | 
            +
                    updated = proc['status']['updatedReplicas'].to_i
         | 
| 87 | 
            +
                    replicas = proc['status']['replicas'].to_i
         | 
| 88 | 
            +
                    scale = proc['spec']['replicas'].to_i
         | 
| 89 | 
            +
                    puts "#{name}: #{command} (#{available}/#{scale}) #{'OUT-OF-DATE' if replicas - updated > 0}"
         | 
| 90 | 
            +
                  end
         | 
| 91 | 
            +
                end
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                def print_cron
         | 
| 94 | 
            +
                  print_section 'Cron'
         | 
| 95 | 
            +
                  json = kubeget 'cronjobs'
         | 
| 96 | 
            +
                  json['items'].each do |cron|
         | 
| 97 | 
            +
                    name = cron['metadata']['name']
         | 
| 98 | 
            +
                    schedule = cron['spec']['schedule']
         | 
| 99 | 
            +
                    command = cron['spec']['jobTemplate']['spec']['template']['spec']['containers'][0]['command'].shelljoin
         | 
| 100 | 
            +
                    last = cron['status']['lastScheduleTime']
         | 
| 101 | 
            +
                    puts "#{name}: #{schedule} #{command} (#{time_ago_in_words last})"
         | 
| 102 | 
            +
                  end
         | 
| 103 | 
            +
                end
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                def print_pods
         | 
| 106 | 
            +
                  print_section 'Pods'
         | 
| 107 | 
            +
                  json = kubeget 'pods'
         | 
| 108 | 
            +
                  json['items'].each do |pod|
         | 
| 109 | 
            +
                    name = pod['metadata']['name']
         | 
| 110 | 
            +
                    created_at = pod['metadata']['creationTimestamp']
         | 
| 111 | 
            +
                    pod_status = pod['status']['phase']
         | 
| 112 | 
            +
                    container_ready = pod['status']['containerStatuses'][0]['ready']
         | 
| 113 | 
            +
                    container_status = pod['status']['containerStatuses'][0]['state'].values.first['reason']
         | 
| 114 | 
            +
                    if pod_status == 'Succeeded' || (pod_status == 'Running' && container_ready)
         | 
| 115 | 
            +
                      puts "#{name}: \e[32m#{container_status || pod_status}\e[0m (#{time_ago_in_words created_at})"
         | 
| 116 | 
            +
                    else
         | 
| 117 | 
            +
                      puts "#{name}: \e[31m#{container_status || pod_status}\e[0m (#{time_ago_in_words created_at})"
         | 
| 118 | 
            +
                    end
         | 
| 119 | 
            +
                  end
         | 
| 120 | 
            +
                end
         | 
| 121 | 
            +
             | 
| 122 | 
            +
                def time_ago_in_words time
         | 
| 123 | 
            +
                  time = Time.parse time unless time.is_a? Time
         | 
| 124 | 
            +
                  seconds = (Time.now - time).round
         | 
| 125 | 
            +
                  case
         | 
| 126 | 
            +
                  when seconds < 60 then "#{seconds}s"
         | 
| 127 | 
            +
                  when seconds < 60*60 then "#{(seconds / 60)}m"
         | 
| 128 | 
            +
                  when seconds < 60*60*24 then "#{(seconds / 60 / 60)}h"
         | 
| 129 | 
            +
                  else "#{(seconds / 60 / 60 / 24)}d"
         | 
| 130 | 
            +
                  end
         | 
| 131 | 
            +
                end
         | 
| 132 | 
            +
             | 
| 133 | 
            +
              end
         | 
| 134 | 
            +
            end
         | 
| @@ -0,0 +1,18 @@ | |
| 1 | 
            +
            module Cuber::Commands
         | 
| 2 | 
            +
              class Logs
         | 
| 3 | 
            +
                include Cuber::Utils
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                def initialize options
         | 
| 6 | 
            +
                  @options = options
         | 
| 7 | 
            +
                end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                def execute
         | 
| 10 | 
            +
                  pod = ARGV.first
         | 
| 11 | 
            +
                  cmd = ['logs']
         | 
| 12 | 
            +
                  cmd += pod ? [pod] : ['-l', "app.kubernetes.io/name=#{@options[:app]}"]
         | 
| 13 | 
            +
                  cmd += ['--all-containers']
         | 
| 14 | 
            +
                  kubectl *cmd
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
            end
         | 
| @@ -0,0 +1,48 @@ | |
| 1 | 
            +
            module Cuber::Commands
         | 
| 2 | 
            +
              class Run
         | 
| 3 | 
            +
                include Cuber::Utils
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                def initialize options
         | 
| 6 | 
            +
                  @options = options
         | 
| 7 | 
            +
                end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                def execute
         | 
| 10 | 
            +
                  set_current_release
         | 
| 11 | 
            +
                  kubeexec command
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                private
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                def set_current_release
         | 
| 17 | 
            +
                  json = kubeget 'namespace', @options[:app]
         | 
| 18 | 
            +
                  @options[:app] = json['metadata']['labels']['app.kubernetes.io/name']
         | 
| 19 | 
            +
                  @options[:release] = json['metadata']['labels']['app.kubernetes.io/version']
         | 
| 20 | 
            +
                  @options[:image] = json['metadata']['annotations']['image']
         | 
| 21 | 
            +
                  @options[:buildpacks] = json['metadata']['annotations']['buildpacks']
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                def command
         | 
| 25 | 
            +
                  if ARGV.length == 0
         | 
| 26 | 
            +
                    'sh'
         | 
| 27 | 
            +
                  elsif ARGV.length == 1
         | 
| 28 | 
            +
                    ARGV.first
         | 
| 29 | 
            +
                  else
         | 
| 30 | 
            +
                    ARGV.shelljoin
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                def kubeexec command
         | 
| 35 | 
            +
                  @options[:pod] = "pod-#{command.downcase.gsub(/[^a-z0-9]+/, '-')}-#{Time.now.utc.iso8601.delete('^0-9')}"
         | 
| 36 | 
            +
                  path = ".cuber/kubernetes/#{@options[:pod]}.yml"
         | 
| 37 | 
            +
                  full_command = command.shellsplit
         | 
| 38 | 
            +
                  full_command.unshift 'launcher' unless @options[:buildpacks].to_s.strip.empty?
         | 
| 39 | 
            +
                  render 'pod.yml', path
         | 
| 40 | 
            +
                  kubectl 'apply', '-f', path
         | 
| 41 | 
            +
                  kubectl 'wait', '--for', 'condition=ready', "pod/#{@options[:pod]}"
         | 
| 42 | 
            +
                  kubectl 'exec', '-it', @options[:pod], '--', *full_command
         | 
| 43 | 
            +
                  kubectl 'delete', 'pod', @options[:pod], '--wait=false'
         | 
| 44 | 
            +
                  File.delete path
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
              end
         | 
| 48 | 
            +
            end
         | 
| @@ -0,0 +1,91 @@ | |
| 1 | 
            +
            module Cuber
         | 
| 2 | 
            +
              class CuberfileParser
         | 
| 3 | 
            +
                def initialize
         | 
| 4 | 
            +
                  @app = nil
         | 
| 5 | 
            +
                  @release = nil
         | 
| 6 | 
            +
                  @repo = nil
         | 
| 7 | 
            +
                  @buildpacks = nil
         | 
| 8 | 
            +
                  @dockerfile = nil
         | 
| 9 | 
            +
                  @image = nil
         | 
| 10 | 
            +
                  @cache = nil
         | 
| 11 | 
            +
                  @dockerconfig = nil
         | 
| 12 | 
            +
                  @kubeconfig = nil
         | 
| 13 | 
            +
                  @migrate = nil
         | 
| 14 | 
            +
                  @procs = {}
         | 
| 15 | 
            +
                  @cron = {}
         | 
| 16 | 
            +
                  @secrets = {}
         | 
| 17 | 
            +
                  @env = {}
         | 
| 18 | 
            +
                  @lb = {}
         | 
| 19 | 
            +
                  @ingress = nil
         | 
| 20 | 
            +
                  @ssl = nil
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                def method_missing m, *args
         | 
| 24 | 
            +
                  abort "Cuberfile: \"#{m}\" is not a command"
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                def app name
         | 
| 28 | 
            +
                  @app = name
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                def release version
         | 
| 32 | 
            +
                  @release = version
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                def repo url, branch: nil
         | 
| 36 | 
            +
                  @repo = { url: url, branch: branch }
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                def buildpacks builder
         | 
| 40 | 
            +
                  @buildpacks = builder
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                def dockerfile path
         | 
| 44 | 
            +
                  @dockerfile = path
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                def image name
         | 
| 48 | 
            +
                  @image = name
         | 
| 49 | 
            +
                end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                def cache enabled
         | 
| 52 | 
            +
                  @cache = enabled
         | 
| 53 | 
            +
                end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                def dockerconfig path
         | 
| 56 | 
            +
                  @dockerconfig = path
         | 
| 57 | 
            +
                end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                def kubeconfig path
         | 
| 60 | 
            +
                  @kubeconfig = path
         | 
| 61 | 
            +
                end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                def migrate cmd, check: nil
         | 
| 64 | 
            +
                  @migrate = { cmd: cmd, check: check }
         | 
| 65 | 
            +
                end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                def proc name, cmd, scale: 1, env: {}
         | 
| 68 | 
            +
                  @procs[name] = { cmd: cmd, scale: scale, env: env }
         | 
| 69 | 
            +
                end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                def cron name, schedule, cmd
         | 
| 72 | 
            +
                  @cron[name] = { schedule: schedule, cmd: cmd }
         | 
| 73 | 
            +
                end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                def env key, value, secret: false
         | 
| 76 | 
            +
                  secret ? (@secrets[key] = value) : (@env[key] = value)
         | 
| 77 | 
            +
                end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                def lb key, value
         | 
| 80 | 
            +
                  @lb[key] = value
         | 
| 81 | 
            +
                end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                def ingress enabled
         | 
| 84 | 
            +
                  @ingress = enabled
         | 
| 85 | 
            +
                end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                def ssl crt, key
         | 
| 88 | 
            +
                  @ssl = { crt: crt, key: key }
         | 
| 89 | 
            +
                end
         | 
| 90 | 
            +
              end
         | 
| 91 | 
            +
            end
         | 
| @@ -0,0 +1,146 @@ | |
| 1 | 
            +
            module Cuber
         | 
| 2 | 
            +
              class CuberfileValidator
         | 
| 3 | 
            +
             | 
| 4 | 
            +
                def initialize options
         | 
| 5 | 
            +
                  @options = options
         | 
| 6 | 
            +
                  @errors = []
         | 
| 7 | 
            +
                end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                def validate
         | 
| 10 | 
            +
                  validate_app
         | 
| 11 | 
            +
                  validate_release
         | 
| 12 | 
            +
                  validate_repo
         | 
| 13 | 
            +
                  validate_buildpacks
         | 
| 14 | 
            +
                  validate_dockerfile
         | 
| 15 | 
            +
                  validate_image
         | 
| 16 | 
            +
                  validate_cache
         | 
| 17 | 
            +
                  validate_dockerconfig
         | 
| 18 | 
            +
                  validate_kubeconfig
         | 
| 19 | 
            +
                  validate_migrate
         | 
| 20 | 
            +
                  validate_procs
         | 
| 21 | 
            +
                  validate_cron
         | 
| 22 | 
            +
                  validate_env
         | 
| 23 | 
            +
                  validate_lb
         | 
| 24 | 
            +
                  validate_ingress
         | 
| 25 | 
            +
                  validate_ssl
         | 
| 26 | 
            +
                  validate_key
         | 
| 27 | 
            +
                  validate_limits
         | 
| 28 | 
            +
                  @errors
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                private
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                def validate_app
         | 
| 34 | 
            +
                  @errors << 'app name must be present' if @options[:app].to_s.strip.empty?
         | 
| 35 | 
            +
                  @errors << 'app name can only include lowercase letters, digits or dashes' if @options[:app] !~ /\A[a-z0-9\-]+\z/
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                def validate_release
         | 
| 39 | 
            +
                  return unless @options[:release]
         | 
| 40 | 
            +
                  @errors << 'release has an invalid format' if @options[:release] !~ /\A[a-zA-Z0-9_\-\.]+\z/
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                def validate_repo
         | 
| 44 | 
            +
                  @errors << 'repo must be present' if @options[:repo].nil? || @options[:repo][:url].to_s.strip.empty?
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                def validate_buildpacks
         | 
| 48 | 
            +
                  return unless @options[:buildpacks]
         | 
| 49 | 
            +
                  @errors << 'buildpacks is not compatible with the dockerfile option' if @options[:dockerfile]
         | 
| 50 | 
            +
                end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                def validate_dockerfile
         | 
| 53 | 
            +
                  return unless @options[:dockerfile]
         | 
| 54 | 
            +
                  @errors << 'dockerfile must be a file' unless File.exists? @options[:dockerfile]
         | 
| 55 | 
            +
                end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                def validate_image
         | 
| 58 | 
            +
                  @errors << 'image must be present' if @options[:image].to_s.strip.empty?
         | 
| 59 | 
            +
                end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                def validate_cache
         | 
| 62 | 
            +
                  return unless @options[:cache]
         | 
| 63 | 
            +
                  @errors << 'cache must be true or false' if @options[:cache] != true && @options[:cache] != false
         | 
| 64 | 
            +
                end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                def validate_dockerconfig
         | 
| 67 | 
            +
                  return unless @options[:dockerconfig]
         | 
| 68 | 
            +
                  @errors << 'dockerconfig must be a file' unless File.exists? @options[:dockerconfig]
         | 
| 69 | 
            +
                end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                def validate_kubeconfig
         | 
| 72 | 
            +
                  @errors << 'kubeconfig must be present' if @options[:kubeconfig].to_s.strip.empty?
         | 
| 73 | 
            +
                  @errors << 'kubeconfig must be a file' unless File.exists? @options[:kubeconfig]
         | 
| 74 | 
            +
                end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                def validate_migrate
         | 
| 77 | 
            +
                  return unless @options[:migrate]
         | 
| 78 | 
            +
                  @errors << 'migrate command must be present' if @options[:migrate][:cmd].to_s.strip.empty?
         | 
| 79 | 
            +
                end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                def validate_procs
         | 
| 82 | 
            +
                  @options[:procs].each do |procname, proc|
         | 
| 83 | 
            +
                    @errors << "proc \"#{procname}\" name can only include lowercase letters" if procname !~ /\A[a-z]+\z/
         | 
| 84 | 
            +
                    @errors << "proc \"#{procname}\" command must be present" if proc[:cmd].to_s.strip.empty?
         | 
| 85 | 
            +
                    @errors << "proc \"#{procname}\" scale must be a positive number" unless proc[:scale].is_a?(Integer) && proc[:scale] > 0
         | 
| 86 | 
            +
                    proc[:env].each do |key, value|
         | 
| 87 | 
            +
                      @errors << "proc \"#{procname}\" env name can only include uppercase letters, digits or underscores" if key !~ /\A[A-Z_]+[A-Z0-9_]*\z/
         | 
| 88 | 
            +
                    end
         | 
| 89 | 
            +
                  end
         | 
| 90 | 
            +
                end
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                def validate_cron
         | 
| 93 | 
            +
                  @options[:cron].each do |jobname, cron|
         | 
| 94 | 
            +
                    @errors << "cron \"#{jobname}\" name can only include lowercase letters" if jobname !~ /\A[a-z]+\z/
         | 
| 95 | 
            +
                    @errors << "cron \"#{jobname}\" schedule must be present" if cron[:schedule].to_s.strip.empty?
         | 
| 96 | 
            +
                    @errors << "cron \"#{jobname}\" command must be present" if cron[:cmd].to_s.strip.empty?
         | 
| 97 | 
            +
                  end
         | 
| 98 | 
            +
                end
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                def validate_env
         | 
| 101 | 
            +
                  @options[:env].merge(@options[:secrets]).each do |key, value|
         | 
| 102 | 
            +
                    @errors << "env \"#{key}\" name can only include uppercase letters, digits or underscores" if key !~ /\A[A-Z_]+[A-Z0-9_]*\z/
         | 
| 103 | 
            +
                  end
         | 
| 104 | 
            +
                end
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                def validate_lb
         | 
| 107 | 
            +
                  @options[:lb].each do |key, value|
         | 
| 108 | 
            +
                    @errors << "lb \"#{key}\" key can only include letters, digits, underscores, dashes, dots or slash" if key !~ /\A[a-zA-Z0-9_\-\.\/]+\z/
         | 
| 109 | 
            +
                  end
         | 
| 110 | 
            +
                end
         | 
| 111 | 
            +
             | 
| 112 | 
            +
                def validate_ingress
         | 
| 113 | 
            +
                  return unless @options[:ingress]
         | 
| 114 | 
            +
                  @errors << 'ingress must be true or false' if @options[:ingress] != true && @options[:ingress] != false
         | 
| 115 | 
            +
                end
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                def validate_ssl
         | 
| 118 | 
            +
                  return unless @options[:ssl]
         | 
| 119 | 
            +
                  @errors << 'ssl crt must be a file' unless File.exists? @options[:ssl][:crt]
         | 
| 120 | 
            +
                  @errors << 'ssl key must be a file' unless File.exists? @options[:ssl][:key]
         | 
| 121 | 
            +
                end
         | 
| 122 | 
            +
                
         | 
| 123 | 
            +
                def validate_key
         | 
| 124 | 
            +
                  return unless File.exists? File.expand_path '~/.cuber.key'
         | 
| 125 | 
            +
                  token = File.read File.expand_path '~/.cuber.key'
         | 
| 126 | 
            +
                  ecdsa_public = OpenSSL::PKey.read <<~PEM
         | 
| 127 | 
            +
                    -----BEGIN PUBLIC KEY-----
         | 
| 128 | 
            +
                    MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAERAh4uT9yojc06y5wgU6CY6sr0Hrv
         | 
| 129 | 
            +
                    P8AUw6uw2PgUdbm7DKkJwFvQYMj3g+TmrxmPV3KQ8uzegfYRbHr6DyonNQ==
         | 
| 130 | 
            +
                    -----END PUBLIC KEY-----
         | 
| 131 | 
            +
                  PEM
         | 
| 132 | 
            +
                  JWT.decode token, ecdsa_public, true, { iss: 'Cuber', verify_iss: true, algorithm: 'ES256' }
         | 
| 133 | 
            +
                rescue JWT::DecodeError
         | 
| 134 | 
            +
                  @errors << 'your license key is invalid or expired'
         | 
| 135 | 
            +
                end
         | 
| 136 | 
            +
                
         | 
| 137 | 
            +
                def validate_limits
         | 
| 138 | 
            +
                  return if File.exists? File.expand_path '~/.cuber.key'
         | 
| 139 | 
            +
                  scale = @options[:procs].collect { |procname, proc| proc[:scale].to_i }.sum
         | 
| 140 | 
            +
                  @errors << 'please purchase a license key or reduce the number of procs' if scale > 5 
         | 
| 141 | 
            +
                end
         | 
| 142 | 
            +
             | 
| 143 | 
            +
              end
         | 
| 144 | 
            +
            end
         | 
| 145 | 
            +
             | 
| 146 | 
            +
            Cuber::CuberfileValidator.freeze
         | 
| @@ -0,0 +1,332 @@ | |
| 1 | 
            +
            kind: Namespace
         | 
| 2 | 
            +
            apiVersion: v1
         | 
| 3 | 
            +
            metadata:
         | 
| 4 | 
            +
              name: <%= @options[:app] %>
         | 
| 5 | 
            +
              labels:
         | 
| 6 | 
            +
                app.kubernetes.io/name: <%= @options[:app] %>
         | 
| 7 | 
            +
                app.kubernetes.io/instance: <%= @options[:instance] %>
         | 
| 8 | 
            +
                app.kubernetes.io/version: <%= @options[:release] %>
         | 
| 9 | 
            +
                app.kubernetes.io/managed-by: cuber
         | 
| 10 | 
            +
              annotations:
         | 
| 11 | 
            +
                image: <%= @options[:image].to_s.to_json %>
         | 
| 12 | 
            +
                buildpacks: <%= @options[:buildpacks].to_s.to_json %>
         | 
| 13 | 
            +
                ingress: <%= @options[:ingress].to_s.to_json %>
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            ---
         | 
| 16 | 
            +
            apiVersion: v1
         | 
| 17 | 
            +
            kind: Secret
         | 
| 18 | 
            +
            metadata:
         | 
| 19 | 
            +
              name: regcred
         | 
| 20 | 
            +
              namespace: <%= @options[:app] %>
         | 
| 21 | 
            +
              labels:
         | 
| 22 | 
            +
                app.kubernetes.io/name: <%= @options[:app] %>
         | 
| 23 | 
            +
                app.kubernetes.io/instance: <%= @options[:instance] %>
         | 
| 24 | 
            +
                app.kubernetes.io/version: <%= @options[:release] %>
         | 
| 25 | 
            +
                app.kubernetes.io/managed-by: cuber
         | 
| 26 | 
            +
            data:
         | 
| 27 | 
            +
              .dockerconfigjson: <%= @options[:dockerconfigjson] %>
         | 
| 28 | 
            +
            type: kubernetes.io/dockerconfigjson
         | 
| 29 | 
            +
             | 
| 30 | 
            +
            ---
         | 
| 31 | 
            +
            apiVersion: v1
         | 
| 32 | 
            +
            kind: Secret
         | 
| 33 | 
            +
            metadata:
         | 
| 34 | 
            +
              name: app-secrets
         | 
| 35 | 
            +
              namespace: <%= @options[:app] %>
         | 
| 36 | 
            +
              labels:
         | 
| 37 | 
            +
                app.kubernetes.io/name: <%= @options[:app] %>
         | 
| 38 | 
            +
                app.kubernetes.io/instance: <%= @options[:instance] %>
         | 
| 39 | 
            +
                app.kubernetes.io/version: <%= @options[:release] %>
         | 
| 40 | 
            +
                app.kubernetes.io/managed-by: cuber
         | 
| 41 | 
            +
            data:
         | 
| 42 | 
            +
              <%- @options[:secrets].each do |key, value| -%>
         | 
| 43 | 
            +
              <%= key %>: <%= Base64.strict_encode64 value %>
         | 
| 44 | 
            +
              <%- end -%>
         | 
| 45 | 
            +
             | 
| 46 | 
            +
            ---
         | 
| 47 | 
            +
            apiVersion: v1
         | 
| 48 | 
            +
            kind: ConfigMap
         | 
| 49 | 
            +
            metadata:
         | 
| 50 | 
            +
              name: env
         | 
| 51 | 
            +
              namespace: <%= @options[:app] %>
         | 
| 52 | 
            +
              labels:
         | 
| 53 | 
            +
                app.kubernetes.io/name: <%= @options[:app] %>
         | 
| 54 | 
            +
                app.kubernetes.io/instance: <%= @options[:instance] %>
         | 
| 55 | 
            +
                app.kubernetes.io/version: <%= @options[:release] %>
         | 
| 56 | 
            +
                app.kubernetes.io/managed-by: cuber
         | 
| 57 | 
            +
            data:
         | 
| 58 | 
            +
              <%- @options[:env].each do |key, value| -%>
         | 
| 59 | 
            +
              <%= key %>: <%= value.to_s.to_json %>
         | 
| 60 | 
            +
              <%- end -%>
         | 
| 61 | 
            +
             | 
| 62 | 
            +
            <%- if @options[:migrate] -%>
         | 
| 63 | 
            +
            ---
         | 
| 64 | 
            +
            apiVersion: batch/v1
         | 
| 65 | 
            +
            kind: Job
         | 
| 66 | 
            +
            metadata:
         | 
| 67 | 
            +
              name: migrate-<%= @options[:instance] %>
         | 
| 68 | 
            +
              namespace: <%= @options[:app] %>
         | 
| 69 | 
            +
              labels:
         | 
| 70 | 
            +
                app.kubernetes.io/name: <%= @options[:app] %>
         | 
| 71 | 
            +
                app.kubernetes.io/instance: <%= @options[:instance] %>
         | 
| 72 | 
            +
                app.kubernetes.io/version: <%= @options[:release] %>
         | 
| 73 | 
            +
                app.kubernetes.io/managed-by: cuber
         | 
| 74 | 
            +
            spec:
         | 
| 75 | 
            +
              template:
         | 
| 76 | 
            +
                metadata:
         | 
| 77 | 
            +
                  labels:
         | 
| 78 | 
            +
                    app.kubernetes.io/name: <%= @options[:app] %>
         | 
| 79 | 
            +
                    app.kubernetes.io/instance: <%= @options[:instance] %>
         | 
| 80 | 
            +
                    app.kubernetes.io/version: <%= @options[:release] %>
         | 
| 81 | 
            +
                    app.kubernetes.io/managed-by: cuber
         | 
| 82 | 
            +
                spec:
         | 
| 83 | 
            +
                  containers:
         | 
| 84 | 
            +
                  - name: migration
         | 
| 85 | 
            +
                    image: <%= @options[:image] %>:<%= @options[:release] %>
         | 
| 86 | 
            +
                    imagePullPolicy: Always
         | 
| 87 | 
            +
                    <%- if @options[:buildpacks] -%>
         | 
| 88 | 
            +
                    command: ["launcher"]
         | 
| 89 | 
            +
                    args: <%= @options[:migrate][:cmd].shellsplit %>
         | 
| 90 | 
            +
                    <%- else -%>
         | 
| 91 | 
            +
                    command: <%= @options[:migrate][:cmd].shellsplit %>
         | 
| 92 | 
            +
                    <%- end -%>
         | 
| 93 | 
            +
                    envFrom:
         | 
| 94 | 
            +
                    - configMapRef:
         | 
| 95 | 
            +
                        name: env
         | 
| 96 | 
            +
                    - secretRef:
         | 
| 97 | 
            +
                        name: app-secrets
         | 
| 98 | 
            +
                  imagePullSecrets:
         | 
| 99 | 
            +
                  - name: regcred
         | 
| 100 | 
            +
                  restartPolicy: Never
         | 
| 101 | 
            +
            <%- end -%>
         | 
| 102 | 
            +
             | 
| 103 | 
            +
            <%- @options[:procs].each do |procname, proc| -%>
         | 
| 104 | 
            +
            ---
         | 
| 105 | 
            +
            apiVersion: apps/v1
         | 
| 106 | 
            +
            kind: Deployment
         | 
| 107 | 
            +
            metadata:
         | 
| 108 | 
            +
              name: <%= procname %>
         | 
| 109 | 
            +
              namespace: <%= @options[:app] %>
         | 
| 110 | 
            +
              labels:
         | 
| 111 | 
            +
                app.kubernetes.io/name: <%= @options[:app] %>
         | 
| 112 | 
            +
                app.kubernetes.io/instance: <%= @options[:instance] %>
         | 
| 113 | 
            +
                app.kubernetes.io/version: <%= @options[:release] %>
         | 
| 114 | 
            +
                app.kubernetes.io/managed-by: cuber
         | 
| 115 | 
            +
            spec:
         | 
| 116 | 
            +
              revisionHistoryLimit: 0
         | 
| 117 | 
            +
              replicas: <%= proc[:scale] %>
         | 
| 118 | 
            +
              selector:
         | 
| 119 | 
            +
                matchLabels:
         | 
| 120 | 
            +
                  app: <%= procname %>-proc
         | 
| 121 | 
            +
              template:
         | 
| 122 | 
            +
                metadata:
         | 
| 123 | 
            +
                  labels:
         | 
| 124 | 
            +
                    app.kubernetes.io/name: <%= @options[:app] %>
         | 
| 125 | 
            +
                    app.kubernetes.io/instance: <%= @options[:instance] %>
         | 
| 126 | 
            +
                    app.kubernetes.io/version: <%= @options[:release] %>
         | 
| 127 | 
            +
                    app.kubernetes.io/managed-by: cuber
         | 
| 128 | 
            +
                    app: <%= procname %>-proc
         | 
| 129 | 
            +
                spec:
         | 
| 130 | 
            +
                  containers:
         | 
| 131 | 
            +
                  - name: <%= procname %>-proc
         | 
| 132 | 
            +
                    image: <%= @options[:image] %>:<%= @options[:release] %>
         | 
| 133 | 
            +
                    imagePullPolicy: Always
         | 
| 134 | 
            +
                    <%- if @options[:buildpacks] -%>
         | 
| 135 | 
            +
                    command: ["launcher"]
         | 
| 136 | 
            +
                    args: <%= proc[:cmd].shellsplit %>
         | 
| 137 | 
            +
                    <%- else -%>
         | 
| 138 | 
            +
                    command: <%= proc[:cmd].shellsplit %>
         | 
| 139 | 
            +
                    <%- end -%>
         | 
| 140 | 
            +
                    envFrom:
         | 
| 141 | 
            +
                    - configMapRef:
         | 
| 142 | 
            +
                        name: env
         | 
| 143 | 
            +
                    - secretRef:
         | 
| 144 | 
            +
                        name: app-secrets
         | 
| 145 | 
            +
                    env:
         | 
| 146 | 
            +
                    <%- proc[:env].each do |key, value| -%>
         | 
| 147 | 
            +
                    - name: <%= key %>
         | 
| 148 | 
            +
                      value: <%= value.to_s.to_json %>
         | 
| 149 | 
            +
                    <%- end -%>
         | 
| 150 | 
            +
                    <%- if procname.to_s == 'web' -%>
         | 
| 151 | 
            +
                    - name: PORT
         | 
| 152 | 
            +
                      value: "8080"
         | 
| 153 | 
            +
                    ports:
         | 
| 154 | 
            +
                    - containerPort: 8080
         | 
| 155 | 
            +
                    readinessProbe:
         | 
| 156 | 
            +
                      httpGet:
         | 
| 157 | 
            +
                        path: /
         | 
| 158 | 
            +
                        port: 8080
         | 
| 159 | 
            +
                    <%- end -%>
         | 
| 160 | 
            +
                  <%- if @options[:migrate] && @options[:migrate][:check] -%>
         | 
| 161 | 
            +
                  initContainers:
         | 
| 162 | 
            +
                  - name: migration-check
         | 
| 163 | 
            +
                    image: <%= @options[:image] %>:<%= @options[:release] %>
         | 
| 164 | 
            +
                    imagePullPolicy: Always
         | 
| 165 | 
            +
                    <%- if @options[:buildpacks] -%>
         | 
| 166 | 
            +
                    command: ["launcher"]
         | 
| 167 | 
            +
                    args: <%= @options[:migrate][:check].shellsplit %>
         | 
| 168 | 
            +
                    <%- else -%>
         | 
| 169 | 
            +
                    command: <%= @options[:migrate][:check].shellsplit %>
         | 
| 170 | 
            +
                    <%- end -%>
         | 
| 171 | 
            +
                    envFrom:
         | 
| 172 | 
            +
                    - configMapRef:
         | 
| 173 | 
            +
                        name: env
         | 
| 174 | 
            +
                    - secretRef:
         | 
| 175 | 
            +
                        name: app-secrets
         | 
| 176 | 
            +
                  <%- end -%>
         | 
| 177 | 
            +
                  imagePullSecrets:
         | 
| 178 | 
            +
                  - name: regcred
         | 
| 179 | 
            +
            <%- end -%>
         | 
| 180 | 
            +
             | 
| 181 | 
            +
            <%- @options[:cron].each do |jobname, cron| -%>
         | 
| 182 | 
            +
            ---
         | 
| 183 | 
            +
            apiVersion: batch/v1
         | 
| 184 | 
            +
            kind: CronJob
         | 
| 185 | 
            +
            metadata:
         | 
| 186 | 
            +
              name: cron-<%= jobname %>
         | 
| 187 | 
            +
              namespace: <%= @options[:app] %>
         | 
| 188 | 
            +
              labels:
         | 
| 189 | 
            +
                app.kubernetes.io/name: <%= @options[:app] %>
         | 
| 190 | 
            +
                app.kubernetes.io/instance: <%= @options[:instance] %>
         | 
| 191 | 
            +
                app.kubernetes.io/version: <%= @options[:release] %>
         | 
| 192 | 
            +
                app.kubernetes.io/managed-by: cuber
         | 
| 193 | 
            +
            spec:
         | 
| 194 | 
            +
              schedule: <%= cron[:schedule].to_s.to_json %>
         | 
| 195 | 
            +
              concurrencyPolicy: Forbid
         | 
| 196 | 
            +
              successfulJobsHistoryLimit: 1
         | 
| 197 | 
            +
              failedJobsHistoryLimit: 1
         | 
| 198 | 
            +
              jobTemplate:
         | 
| 199 | 
            +
                metadata:
         | 
| 200 | 
            +
                  labels:
         | 
| 201 | 
            +
                    app.kubernetes.io/name: <%= @options[:app] %>
         | 
| 202 | 
            +
                    app.kubernetes.io/instance: <%= @options[:instance] %>
         | 
| 203 | 
            +
                    app.kubernetes.io/version: <%= @options[:release] %>
         | 
| 204 | 
            +
                    app.kubernetes.io/managed-by: cuber
         | 
| 205 | 
            +
                spec:
         | 
| 206 | 
            +
                  backoffLimit: 0
         | 
| 207 | 
            +
                  template:
         | 
| 208 | 
            +
                    metadata:
         | 
| 209 | 
            +
                      labels:
         | 
| 210 | 
            +
                        app.kubernetes.io/name: <%= @options[:app] %>
         | 
| 211 | 
            +
                        app.kubernetes.io/instance: <%= @options[:instance] %>
         | 
| 212 | 
            +
                        app.kubernetes.io/version: <%= @options[:release] %>
         | 
| 213 | 
            +
                        app.kubernetes.io/managed-by: cuber
         | 
| 214 | 
            +
                    spec:
         | 
| 215 | 
            +
                      containers:
         | 
| 216 | 
            +
                      - name: task
         | 
| 217 | 
            +
                        image: <%= @options[:image] %>:<%= @options[:release] %>
         | 
| 218 | 
            +
                        imagePullPolicy: Always
         | 
| 219 | 
            +
                        <%- if @options[:buildpacks] -%>
         | 
| 220 | 
            +
                        command: ["launcher"]
         | 
| 221 | 
            +
                        args: <%= cron[:cmd].shellsplit %>
         | 
| 222 | 
            +
                        <%- else -%>
         | 
| 223 | 
            +
                        command: <%= cron[:cmd].shellsplit %>
         | 
| 224 | 
            +
                        <%- end -%>
         | 
| 225 | 
            +
                        envFrom:
         | 
| 226 | 
            +
                        - configMapRef:
         | 
| 227 | 
            +
                            name: env
         | 
| 228 | 
            +
                        - secretRef:
         | 
| 229 | 
            +
                            name: app-secrets
         | 
| 230 | 
            +
                      imagePullSecrets:
         | 
| 231 | 
            +
                      - name: regcred
         | 
| 232 | 
            +
                      restartPolicy: Never
         | 
| 233 | 
            +
            <%- end -%>
         | 
| 234 | 
            +
             | 
| 235 | 
            +
            <%- if @options[:ssl] -%>
         | 
| 236 | 
            +
            ---
         | 
| 237 | 
            +
            apiVersion: v1
         | 
| 238 | 
            +
            kind: Secret
         | 
| 239 | 
            +
            metadata:
         | 
| 240 | 
            +
              name: ssl
         | 
| 241 | 
            +
              namespace: <%= @options[:app] %>
         | 
| 242 | 
            +
              labels:
         | 
| 243 | 
            +
                app.kubernetes.io/name: <%= @options[:app] %>
         | 
| 244 | 
            +
                app.kubernetes.io/instance: <%= @options[:instance] %>
         | 
| 245 | 
            +
                app.kubernetes.io/version: <%= @options[:release] %>
         | 
| 246 | 
            +
                app.kubernetes.io/managed-by: cuber
         | 
| 247 | 
            +
            data:
         | 
| 248 | 
            +
              tls.crt: <%= Base64.strict_encode64 File.read @options[:ssl][:crt] %>
         | 
| 249 | 
            +
              tls.key: <%= Base64.strict_encode64 File.read @options[:ssl][:key] %>
         | 
| 250 | 
            +
            type: kubernetes.io/tls
         | 
| 251 | 
            +
            <%- end -%>
         | 
| 252 | 
            +
             | 
| 253 | 
            +
            <%- if @options[:ingress] -%>
         | 
| 254 | 
            +
            ---
         | 
| 255 | 
            +
            apiVersion: v1
         | 
| 256 | 
            +
            kind: Service
         | 
| 257 | 
            +
            metadata:
         | 
| 258 | 
            +
              name: web-service
         | 
| 259 | 
            +
              namespace: <%= @options[:app] %>
         | 
| 260 | 
            +
              labels:
         | 
| 261 | 
            +
                app.kubernetes.io/name: <%= @options[:app] %>
         | 
| 262 | 
            +
                app.kubernetes.io/instance: <%= @options[:instance] %>
         | 
| 263 | 
            +
                app.kubernetes.io/version: <%= @options[:release] %>
         | 
| 264 | 
            +
                app.kubernetes.io/managed-by: cuber
         | 
| 265 | 
            +
            spec:
         | 
| 266 | 
            +
              selector:
         | 
| 267 | 
            +
                app: web-proc
         | 
| 268 | 
            +
              ports:
         | 
| 269 | 
            +
                - protocol: TCP
         | 
| 270 | 
            +
                  port: 80
         | 
| 271 | 
            +
                  targetPort: 8080
         | 
| 272 | 
            +
             | 
| 273 | 
            +
            ---
         | 
| 274 | 
            +
            apiVersion: networking.k8s.io/v1
         | 
| 275 | 
            +
            kind: Ingress
         | 
| 276 | 
            +
            metadata:
         | 
| 277 | 
            +
              name: web-ingress
         | 
| 278 | 
            +
              namespace: <%= @options[:app] %>
         | 
| 279 | 
            +
              labels:
         | 
| 280 | 
            +
                app.kubernetes.io/name: <%= @options[:app] %>
         | 
| 281 | 
            +
                app.kubernetes.io/instance: <%= @options[:instance] %>
         | 
| 282 | 
            +
                app.kubernetes.io/version: <%= @options[:release] %>
         | 
| 283 | 
            +
                app.kubernetes.io/managed-by: cuber
         | 
| 284 | 
            +
              annotations:
         | 
| 285 | 
            +
                <%- @options[:lb].each do |key, value| -%>
         | 
| 286 | 
            +
                <%= key %>: <%= value.to_s.to_json %>
         | 
| 287 | 
            +
                <%- end -%>
         | 
| 288 | 
            +
            spec:
         | 
| 289 | 
            +
              <%- if @options[:ssl] -%>
         | 
| 290 | 
            +
              tls:
         | 
| 291 | 
            +
              - secretName: ssl
         | 
| 292 | 
            +
              <%- end -%>
         | 
| 293 | 
            +
              rules:
         | 
| 294 | 
            +
              - http:
         | 
| 295 | 
            +
                  paths:
         | 
| 296 | 
            +
                  - path: /
         | 
| 297 | 
            +
                    pathType: Prefix
         | 
| 298 | 
            +
                    backend:
         | 
| 299 | 
            +
                      service:
         | 
| 300 | 
            +
                        name: web-service
         | 
| 301 | 
            +
                        port:
         | 
| 302 | 
            +
                          number: 80
         | 
| 303 | 
            +
            <%- else -%>
         | 
| 304 | 
            +
            ---
         | 
| 305 | 
            +
            apiVersion: v1
         | 
| 306 | 
            +
            kind: Service
         | 
| 307 | 
            +
            metadata:
         | 
| 308 | 
            +
              name: load-balancer
         | 
| 309 | 
            +
              namespace: <%= @options[:app] %>
         | 
| 310 | 
            +
              labels:
         | 
| 311 | 
            +
                app.kubernetes.io/name: <%= @options[:app] %>
         | 
| 312 | 
            +
                app.kubernetes.io/instance: <%= @options[:instance] %>
         | 
| 313 | 
            +
                app.kubernetes.io/version: <%= @options[:release] %>
         | 
| 314 | 
            +
                app.kubernetes.io/managed-by: cuber
         | 
| 315 | 
            +
              annotations:
         | 
| 316 | 
            +
                <%- @options[:lb].each do |key, value| -%>
         | 
| 317 | 
            +
                <%= key %>: <%= value.to_s.to_json %>
         | 
| 318 | 
            +
                <%- end -%>
         | 
| 319 | 
            +
            spec:
         | 
| 320 | 
            +
              type: LoadBalancer
         | 
| 321 | 
            +
              selector:
         | 
| 322 | 
            +
                app: web-proc
         | 
| 323 | 
            +
              ports:
         | 
| 324 | 
            +
              - name: http
         | 
| 325 | 
            +
                protocol: TCP
         | 
| 326 | 
            +
                port: 80
         | 
| 327 | 
            +
                targetPort: 8080
         | 
| 328 | 
            +
              - name: https
         | 
| 329 | 
            +
                protocol: TCP
         | 
| 330 | 
            +
                port: 443
         | 
| 331 | 
            +
                targetPort: 8080
         | 
| 332 | 
            +
            <%- end -%>
         | 
| @@ -0,0 +1,22 @@ | |
| 1 | 
            +
            apiVersion: v1
         | 
| 2 | 
            +
            kind: Pod
         | 
| 3 | 
            +
            metadata:
         | 
| 4 | 
            +
              name: <%= @options[:pod] %>
         | 
| 5 | 
            +
              namespace: <%= @options[:app] %>
         | 
| 6 | 
            +
              labels:
         | 
| 7 | 
            +
                app.kubernetes.io/name: <%= @options[:app] %>
         | 
| 8 | 
            +
                app.kubernetes.io/version: <%= @options[:release] %>
         | 
| 9 | 
            +
                app.kubernetes.io/managed-by: cuber
         | 
| 10 | 
            +
            spec:
         | 
| 11 | 
            +
              containers:
         | 
| 12 | 
            +
              - name: pod-proc
         | 
| 13 | 
            +
                image: <%= @options[:image] %>:<%= @options[:release] %>
         | 
| 14 | 
            +
                imagePullPolicy: Always
         | 
| 15 | 
            +
                command: ["sleep", "infinity"]
         | 
| 16 | 
            +
                envFrom:
         | 
| 17 | 
            +
                - configMapRef:
         | 
| 18 | 
            +
                    name: env
         | 
| 19 | 
            +
                - secretRef:
         | 
| 20 | 
            +
                    name: app-secrets
         | 
| 21 | 
            +
              imagePullSecrets:
         | 
| 22 | 
            +
              - name: regcred
         | 
    
        data/lib/cuber/utils.rb
    ADDED
    
    | @@ -0,0 +1,24 @@ | |
| 1 | 
            +
            module Cuber::Utils
         | 
| 2 | 
            +
             | 
| 3 | 
            +
              def kubectl *args
         | 
| 4 | 
            +
                cmd = ['kubectl', '--kubeconfig', @options[:kubeconfig], '-n', @options[:app]] + args
         | 
| 5 | 
            +
                system(*cmd) || abort("Cuber: \"#{cmd.shelljoin}\" failed")
         | 
| 6 | 
            +
              end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              def kubeget type, name = nil, *args
         | 
| 9 | 
            +
                cmd = ['kubectl', 'get', type, name, '-o', 'json', '--kubeconfig', @options[:kubeconfig], '-n', @options[:app], *args].compact
         | 
| 10 | 
            +
                out, status = Open3.capture2 *cmd
         | 
| 11 | 
            +
                abort "Cuber: \"#{cmd.shelljoin}\" failed" unless status.success?
         | 
| 12 | 
            +
                out.empty? ? nil : JSON.parse(out)
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              def render template, target_file = nil
         | 
| 16 | 
            +
                template = File.join __dir__, 'templates', "#{template}.erb"
         | 
| 17 | 
            +
                renderer = ERB.new File.read(template), trim_mode: '-'
         | 
| 18 | 
            +
                content = renderer.result binding
         | 
| 19 | 
            +
                return content unless target_file
         | 
| 20 | 
            +
                FileUtils.mkdir_p File.dirname target_file
         | 
| 21 | 
            +
                File.write target_file, content
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
              
         | 
| 24 | 
            +
            end
         | 
    
        data/lib/cuber.rb
    ADDED
    
    | @@ -0,0 +1,15 @@ | |
| 1 | 
            +
            require 'cuber/version'
         | 
| 2 | 
            +
            require 'cuber/cli'
         | 
| 3 | 
            +
            require 'cuber/cuberfile_parser'
         | 
| 4 | 
            +
            require 'cuber/cuberfile_validator'
         | 
| 5 | 
            +
            require 'cuber/utils'
         | 
| 6 | 
            +
            require 'cuber/commands/version'
         | 
| 7 | 
            +
            require 'cuber/commands/info'
         | 
| 8 | 
            +
            require 'cuber/commands/logs'
         | 
| 9 | 
            +
            require 'cuber/commands/restart'
         | 
| 10 | 
            +
            require 'cuber/commands/run'
         | 
| 11 | 
            +
            require 'cuber/commands/deploy'
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            module Cuber
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,23 +1,57 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: cuber
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version:  | 
| 4 | 
            +
              version: 1.2.1
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Cuber
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date:  | 
| 12 | 
            -
            dependencies: | 
| 11 | 
            +
            date: 2022-06-08 00:00:00.000000000 Z
         | 
| 12 | 
            +
            dependencies:
         | 
| 13 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 14 | 
            +
              name: jwt
         | 
| 15 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 16 | 
            +
                requirements:
         | 
| 17 | 
            +
                - - "~>"
         | 
| 18 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 19 | 
            +
                    version: 2.3.0
         | 
| 20 | 
            +
              type: :runtime
         | 
| 21 | 
            +
              prerelease: false
         | 
| 22 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 23 | 
            +
                requirements:
         | 
| 24 | 
            +
                - - "~>"
         | 
| 25 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 26 | 
            +
                    version: 2.3.0
         | 
| 13 27 | 
             
            description:
         | 
| 14 28 | 
             
            email:
         | 
| 15 | 
            -
            executables: | 
| 29 | 
            +
            executables:
         | 
| 30 | 
            +
            - cuber
         | 
| 16 31 | 
             
            extensions: []
         | 
| 17 32 | 
             
            extra_rdoc_files: []
         | 
| 18 | 
            -
            files: | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 33 | 
            +
            files:
         | 
| 34 | 
            +
            - README.md
         | 
| 35 | 
            +
            - SSAL-LICENSE
         | 
| 36 | 
            +
            - bin/cuber
         | 
| 37 | 
            +
            - cuber.gemspec
         | 
| 38 | 
            +
            - lib/cuber.rb
         | 
| 39 | 
            +
            - lib/cuber/cli.rb
         | 
| 40 | 
            +
            - lib/cuber/commands/deploy.rb
         | 
| 41 | 
            +
            - lib/cuber/commands/info.rb
         | 
| 42 | 
            +
            - lib/cuber/commands/logs.rb
         | 
| 43 | 
            +
            - lib/cuber/commands/restart.rb
         | 
| 44 | 
            +
            - lib/cuber/commands/run.rb
         | 
| 45 | 
            +
            - lib/cuber/commands/version.rb
         | 
| 46 | 
            +
            - lib/cuber/cuberfile_parser.rb
         | 
| 47 | 
            +
            - lib/cuber/cuberfile_validator.rb
         | 
| 48 | 
            +
            - lib/cuber/templates/deployment.yml.erb
         | 
| 49 | 
            +
            - lib/cuber/templates/pod.yml.erb
         | 
| 50 | 
            +
            - lib/cuber/utils.rb
         | 
| 51 | 
            +
            - lib/cuber/version.rb
         | 
| 52 | 
            +
            homepage: https://cuber.cloud
         | 
| 53 | 
            +
            licenses:
         | 
| 54 | 
            +
            - LicenseRef-SSAL-LICENSE
         | 
| 21 55 | 
             
            metadata: {}
         | 
| 22 56 | 
             
            post_install_message:
         | 
| 23 57 | 
             
            rdoc_options: []
         | 
| @@ -34,8 +68,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 34 68 | 
             
                - !ruby/object:Gem::Version
         | 
| 35 69 | 
             
                  version: '0'
         | 
| 36 70 | 
             
            requirements: []
         | 
| 37 | 
            -
            rubygems_version: 3.2. | 
| 71 | 
            +
            rubygems_version: 3.2.33
         | 
| 38 72 | 
             
            signing_key:
         | 
| 39 73 | 
             
            specification_version: 4
         | 
| 40 | 
            -
            summary:  | 
| 74 | 
            +
            summary: Deploy your apps on Kubernetes easily.
         | 
| 41 75 | 
             
            test_files: []
         |