uffizzi-cli 0.1.4.3 → 0.2.0
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/.rubocop.yml +3 -0
- data/Gemfile.lock +5 -1
- data/README.md +67 -26
- data/config/config.rb +17 -0
- data/lib/uffizzi/auth_helper.rb +5 -0
- data/lib/uffizzi/cli/config.rb +28 -20
- data/lib/uffizzi/cli/login.rb +3 -6
- data/lib/uffizzi/cli/preview.rb +267 -0
- data/lib/uffizzi/cli/project/compose.rb +119 -0
- data/lib/uffizzi/cli/project.rb +64 -0
- data/lib/uffizzi/cli.rb +15 -14
- data/lib/uffizzi/clients/api/api_client.rb +71 -5
- data/lib/uffizzi/clients/api/api_routes.rb +24 -0
- data/lib/uffizzi/clients/api/http_client.rb +21 -3
- data/lib/uffizzi/config_file.rb +17 -13
- data/lib/uffizzi/response_helper.rb +24 -0
- data/lib/uffizzi/services/compose_file_service.rb +102 -0
- data/lib/uffizzi/services/env_variables_service.rb +48 -0
- data/lib/uffizzi/version.rb +1 -1
- data/lib/uffizzi.rb +5 -4
- data/man/uffizzi-create +50 -0
- data/man/uffizzi-create.ronn +41 -0
- data/man/uffizzi-delete +37 -0
- data/man/uffizzi-delete.ronn +28 -0
- data/man/uffizzi-describe +38 -0
- data/man/uffizzi-describe.ronn +29 -0
- data/man/uffizzi-list +33 -0
- data/man/uffizzi-list.ronn +25 -0
- data/man/uffizzi-preview +39 -0
- data/man/uffizzi-preview.ronn +33 -0
- data/uffizzi.gemspec +1 -0
- metadata +32 -3
- data/lib/uffizzi/cli/projects.rb +0 -48
| @@ -0,0 +1,119 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'io/console'
         | 
| 4 | 
            +
            require 'uffizzi'
         | 
| 5 | 
            +
            require 'uffizzi/auth_helper'
         | 
| 6 | 
            +
            require 'uffizzi/response_helper'
         | 
| 7 | 
            +
            require 'uffizzi/services/compose_file_service'
         | 
| 8 | 
            +
            require 'uffizzi/services/env_variables_service'
         | 
| 9 | 
            +
            require 'thor'
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            module Uffizzi
         | 
| 12 | 
            +
              class CLI::Project::Compose < Thor
         | 
| 13 | 
            +
                include ApiClient
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                desc 'set', 'set'
         | 
| 16 | 
            +
                def set
         | 
| 17 | 
            +
                  run(options, 'set')
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                desc 'unset', 'unset'
         | 
| 21 | 
            +
                def unset
         | 
| 22 | 
            +
                  run(options, 'unset')
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                desc 'describe', 'describe'
         | 
| 26 | 
            +
                def describe
         | 
| 27 | 
            +
                  run(options, 'describe')
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                private
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                def run(options, command)
         | 
| 33 | 
            +
                  return Uffizzi.ui.say('You are not logged in.') unless Uffizzi::AuthHelper.signed_in?
         | 
| 34 | 
            +
                  return Uffizzi.ui.say('This command needs project to be set in config file') unless Uffizzi::AuthHelper.project_set?
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                  file_path = options[:file]
         | 
| 37 | 
            +
                  case command
         | 
| 38 | 
            +
                  when 'set'
         | 
| 39 | 
            +
                    handle_set_command(file_path)
         | 
| 40 | 
            +
                  when 'unset'
         | 
| 41 | 
            +
                    handle_unset_command
         | 
| 42 | 
            +
                  when 'describe'
         | 
| 43 | 
            +
                    handle_describe_command
         | 
| 44 | 
            +
                  when 'validate'
         | 
| 45 | 
            +
                    handle_validate_command(file_path)
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
                end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                def handle_set_command(file_path)
         | 
| 50 | 
            +
                  return Uffizzi.ui.say('No file provided') if file_path.nil?
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                  hostname = ConfigFile.read_option(:hostname)
         | 
| 53 | 
            +
                  project_slug = ConfigFile.read_option(:project)
         | 
| 54 | 
            +
                  params = prepare_params(file_path)
         | 
| 55 | 
            +
                  response = set_compose_file(hostname, params, project_slug)
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                  if ResponseHelper.created?(response)
         | 
| 58 | 
            +
                    Uffizzi.ui.say('compose file created')
         | 
| 59 | 
            +
                  else
         | 
| 60 | 
            +
                    ResponseHelper.handle_failed_response(response)
         | 
| 61 | 
            +
                  end
         | 
| 62 | 
            +
                end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                def handle_unset_command
         | 
| 65 | 
            +
                  hostname = ConfigFile.read_option(:hostname)
         | 
| 66 | 
            +
                  project_slug = ConfigFile.read_option(:project)
         | 
| 67 | 
            +
                  response = unset_compose_file(hostname, project_slug)
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                  if ResponseHelper.no_content?(response)
         | 
| 70 | 
            +
                    Uffizzi.ui.say('compose file deleted')
         | 
| 71 | 
            +
                  else
         | 
| 72 | 
            +
                    ResponseHelper.handle_failed_response(response)
         | 
| 73 | 
            +
                  end
         | 
| 74 | 
            +
                end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                def handle_describe_command
         | 
| 77 | 
            +
                  hostname = ConfigFile.read_option(:hostname)
         | 
| 78 | 
            +
                  project_slug = ConfigFile.read_option(:project)
         | 
| 79 | 
            +
                  response = describe_compose_file(hostname, project_slug)
         | 
| 80 | 
            +
                  compose_file = response[:body][:compose_file]
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                  if ResponseHelper.ok?(response)
         | 
| 83 | 
            +
                    if compose_file_valid?(compose_file)
         | 
| 84 | 
            +
                      Uffizzi.ui.say(Base64.decode64(compose_file[:content]))
         | 
| 85 | 
            +
                    else
         | 
| 86 | 
            +
                      ResponseHelper.handle_invalid_compose_response(response)
         | 
| 87 | 
            +
                    end
         | 
| 88 | 
            +
                  else
         | 
| 89 | 
            +
                    ResponseHelper.handle_failed_response(response)
         | 
| 90 | 
            +
                  end
         | 
| 91 | 
            +
                end
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                def compose_file_valid?(compose_file)
         | 
| 94 | 
            +
                  compose_file[:state] == 'valid_file'
         | 
| 95 | 
            +
                end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                def prepare_params(file_path)
         | 
| 98 | 
            +
                  begin
         | 
| 99 | 
            +
                    compose_file_data = EnvVariablesService.substitute_env_variables(File.read(file_path))
         | 
| 100 | 
            +
                  rescue Errno::ENOENT => e
         | 
| 101 | 
            +
                    return Uffizzi.ui.say(e)
         | 
| 102 | 
            +
                  end
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                  compose_file_dir = File.dirname(file_path)
         | 
| 105 | 
            +
                  dependencies = ComposeFileService.parse(compose_file_data, compose_file_dir)
         | 
| 106 | 
            +
                  absolute_path = File.absolute_path(file_path)
         | 
| 107 | 
            +
                  compose_file_params = {
         | 
| 108 | 
            +
                    path: absolute_path,
         | 
| 109 | 
            +
                    content: Base64.encode64(compose_file_data),
         | 
| 110 | 
            +
                    source: absolute_path,
         | 
| 111 | 
            +
                  }
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                  {
         | 
| 114 | 
            +
                    compose_file: compose_file_params,
         | 
| 115 | 
            +
                    dependencies: dependencies,
         | 
| 116 | 
            +
                  }
         | 
| 117 | 
            +
                end
         | 
| 118 | 
            +
              end
         | 
| 119 | 
            +
            end
         | 
| @@ -0,0 +1,64 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'io/console'
         | 
| 4 | 
            +
            require 'uffizzi'
         | 
| 5 | 
            +
            require 'uffizzi/auth_helper'
         | 
| 6 | 
            +
            require 'uffizzi/response_helper'
         | 
| 7 | 
            +
            require 'thor'
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            module Uffizzi
         | 
| 10 | 
            +
              class CLI::Project < Thor
         | 
| 11 | 
            +
                include ApiClient
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                desc 'compose', 'compose'
         | 
| 14 | 
            +
                method_option :file, required: false, aliases: '-f'
         | 
| 15 | 
            +
                require_relative 'project/compose'
         | 
| 16 | 
            +
                subcommand 'compose', Uffizzi::CLI::Project::Compose
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                desc 'list', 'list'
         | 
| 19 | 
            +
                def list
         | 
| 20 | 
            +
                  run('list')
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                private
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                def run(command)
         | 
| 26 | 
            +
                  return Uffizzi.ui.say('You are not logged in.') unless Uffizzi::AuthHelper.signed_in?
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  case command
         | 
| 29 | 
            +
                  when 'list'
         | 
| 30 | 
            +
                    handle_list_command
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                def handle_list_command
         | 
| 35 | 
            +
                  hostname = ConfigFile.read_option(:hostname)
         | 
| 36 | 
            +
                  response = fetch_projects(hostname)
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  if ResponseHelper.ok?(response)
         | 
| 39 | 
            +
                    handle_succeed_response(response)
         | 
| 40 | 
            +
                  else
         | 
| 41 | 
            +
                    ResponseHelper.handle_failed_response(response)
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                def handle_succeed_response(response)
         | 
| 46 | 
            +
                  projects = response[:body][:projects]
         | 
| 47 | 
            +
                  return Uffizzi.ui.say('No projects related to this email') if projects.empty?
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                  set_default_project(projects.first) if projects.size == 1
         | 
| 50 | 
            +
                  print_projects(projects)
         | 
| 51 | 
            +
                end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                def print_projects(projects)
         | 
| 54 | 
            +
                  projects_list = projects.reduce('') do |acc, project|
         | 
| 55 | 
            +
                    "#{acc}#{project[:slug]}\n"
         | 
| 56 | 
            +
                  end
         | 
| 57 | 
            +
                  Uffizzi.ui.say(projects_list)
         | 
| 58 | 
            +
                end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                def set_default_project(project)
         | 
| 61 | 
            +
                  ConfigFile.write_option(:project, project[:slug])
         | 
| 62 | 
            +
                end
         | 
| 63 | 
            +
              end
         | 
| 64 | 
            +
            end
         | 
    
        data/lib/uffizzi/cli.rb
    CHANGED
    
    | @@ -1,22 +1,22 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 3 | 
             
            require 'thor'
         | 
| 4 | 
            +
            require 'uffizzi'
         | 
| 4 5 |  | 
| 5 6 | 
             
            module Uffizzi
         | 
| 6 7 | 
             
              class CLI < Thor
         | 
| 7 8 | 
             
                require_relative 'cli/common'
         | 
| 9 | 
            +
                class_option :help, type: :boolean, aliases: ['-h', 'help']
         | 
| 8 10 |  | 
| 9 | 
            -
                 | 
| 10 | 
            -
             | 
| 11 | 
            -
                desc 'version', 'Show Version'
         | 
| 11 | 
            +
                desc 'version', 'show version'
         | 
| 12 12 | 
             
                def version
         | 
| 13 13 | 
             
                  require_relative 'version'
         | 
| 14 | 
            -
                   | 
| 14 | 
            +
                  Uffizzi.ui.say(Uffizzi::VERSION)
         | 
| 15 15 | 
             
                end
         | 
| 16 16 |  | 
| 17 17 | 
             
                desc 'login', 'Login into Uffizzi'
         | 
| 18 18 | 
             
                method_option :user, required: true, aliases: '-u'
         | 
| 19 | 
            -
                method_option :hostname, required: true | 
| 19 | 
            +
                method_option :hostname, required: true
         | 
| 20 20 | 
             
                def login
         | 
| 21 21 | 
             
                  require_relative 'cli/login'
         | 
| 22 22 | 
             
                  Login.new(options).run
         | 
| @@ -30,16 +30,17 @@ module Uffizzi | |
| 30 30 | 
             
                  Logout.new.run
         | 
| 31 31 | 
             
                end
         | 
| 32 32 |  | 
| 33 | 
            -
                desc ' | 
| 34 | 
            -
                 | 
| 35 | 
            -
             | 
| 36 | 
            -
                  Projects.new.run
         | 
| 37 | 
            -
                end
         | 
| 33 | 
            +
                desc 'project', 'project'
         | 
| 34 | 
            +
                require_relative 'cli/project'
         | 
| 35 | 
            +
                subcommand 'project', CLI::Project
         | 
| 38 36 |  | 
| 39 37 | 
             
                desc 'config', 'config'
         | 
| 40 | 
            -
                 | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            -
                 | 
| 38 | 
            +
                require_relative 'cli/config'
         | 
| 39 | 
            +
                subcommand 'config', CLI::Config
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                desc 'preview', 'preview'
         | 
| 42 | 
            +
                method_option :project, required: false
         | 
| 43 | 
            +
                require_relative 'cli/preview'
         | 
| 44 | 
            +
                subcommand 'preview', CLI::Preview
         | 
| 44 45 | 
             
              end
         | 
| 45 46 | 
             
            end
         | 
| @@ -7,27 +7,93 @@ module ApiClient | |
| 7 7 | 
             
              include ApiRoutes
         | 
| 8 8 | 
             
              def create_session(hostname, params = {})
         | 
| 9 9 | 
             
                uri = session_uri(hostname)
         | 
| 10 | 
            -
                response = Uffizzi::HttpClient. | 
| 10 | 
            +
                response = Uffizzi::HttpClient.make_post_request(uri, params, false)
         | 
| 11 11 |  | 
| 12 12 | 
             
                build_response(response)
         | 
| 13 13 | 
             
              end
         | 
| 14 14 |  | 
| 15 15 | 
             
              def destroy_session(hostname)
         | 
| 16 16 | 
             
                uri = session_uri(hostname)
         | 
| 17 | 
            -
                response = Uffizzi::HttpClient. | 
| 17 | 
            +
                response = Uffizzi::HttpClient.make_delete_request(uri)
         | 
| 18 18 |  | 
| 19 19 | 
             
                build_response(response)
         | 
| 20 20 | 
             
              end
         | 
| 21 21 |  | 
| 22 22 | 
             
              def fetch_projects(hostname)
         | 
| 23 23 | 
             
                uri = projects_uri(hostname)
         | 
| 24 | 
            -
                response = Uffizzi::HttpClient. | 
| 24 | 
            +
                response = Uffizzi::HttpClient.make_get_request(uri)
         | 
| 25 25 |  | 
| 26 26 | 
             
                build_response(response)
         | 
| 27 27 | 
             
              end
         | 
| 28 28 |  | 
| 29 | 
            -
              def  | 
| 30 | 
            -
                 | 
| 29 | 
            +
              def set_compose_file(hostname, params, project_slug)
         | 
| 30 | 
            +
                uri = compose_file_uri(hostname, project_slug)
         | 
| 31 | 
            +
                response = Uffizzi::HttpClient.make_post_request(uri, params)
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                build_response(response)
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
              def unset_compose_file(hostname, project_slug)
         | 
| 37 | 
            +
                uri = compose_file_uri(hostname, project_slug)
         | 
| 38 | 
            +
                response = Uffizzi::HttpClient.make_delete_request(uri, true)
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                build_response(response)
         | 
| 41 | 
            +
              end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
              def describe_compose_file(hostname, project_slug)
         | 
| 44 | 
            +
                uri = compose_file_uri(hostname, project_slug)
         | 
| 45 | 
            +
                response = Uffizzi::HttpClient.make_get_request(uri)
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                build_response(response)
         | 
| 48 | 
            +
              end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
              def validate_compose_file(hostname, project_slug)
         | 
| 51 | 
            +
                uri = validate_compose_file_uri(hostname, project_slug)
         | 
| 52 | 
            +
                response = Uffizzi::HttpClient.make_get_request(uri)
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                build_response(response)
         | 
| 55 | 
            +
              end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
              def fetch_deployments(hostname, project_slug)
         | 
| 58 | 
            +
                uri = deployments_uri(hostname, project_slug)
         | 
| 59 | 
            +
                response = Uffizzi::HttpClient.make_get_request(uri)
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                build_response(response)
         | 
| 62 | 
            +
              end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
              def create_deployment(hostname, project_slug, params)
         | 
| 65 | 
            +
                uri = deployments_uri(hostname, project_slug)
         | 
| 66 | 
            +
                response = Uffizzi::HttpClient.make_post_request(uri, params)
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                build_response(response)
         | 
| 69 | 
            +
              end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
              def delete_deployment(hostname, project_slug, deployment_id)
         | 
| 72 | 
            +
                uri = deployment_uri(hostname, project_slug, deployment_id)
         | 
| 73 | 
            +
                response = Uffizzi::HttpClient.make_delete_request(uri, true)
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                build_response(response)
         | 
| 76 | 
            +
              end
         | 
| 77 | 
            +
             | 
| 78 | 
            +
              def describe_deployment(hostname, project_slug, deployment_id)
         | 
| 79 | 
            +
                uri = deployment_uri(hostname, project_slug, deployment_id)
         | 
| 80 | 
            +
                response = Uffizzi::HttpClient.make_get_request(uri)
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                build_response(response)
         | 
| 83 | 
            +
              end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
              def get_activity_items(hostname, project_slug, deployment_id)
         | 
| 86 | 
            +
                uri = activity_items_uri(hostname, project_slug, deployment_id)
         | 
| 87 | 
            +
                response = Uffizzi::HttpClient.make_get_request(uri)
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                build_response(response)
         | 
| 90 | 
            +
              end
         | 
| 91 | 
            +
             | 
| 92 | 
            +
              def deploy_containers(hostname, project_slug, deployment_id, params)
         | 
| 93 | 
            +
                uri = deploy_containers_uri(hostname, project_slug, deployment_id)
         | 
| 94 | 
            +
                response = Uffizzi::HttpClient.make_post_request(uri, params)
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                build_response(response)
         | 
| 31 97 | 
             
              end
         | 
| 32 98 |  | 
| 33 99 | 
             
              private
         | 
| @@ -8,4 +8,28 @@ module ApiRoutes | |
| 8 8 | 
             
              def projects_uri(hostname)
         | 
| 9 9 | 
             
                "#{hostname}/api/cli/v1/projects"
         | 
| 10 10 | 
             
              end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              def compose_file_uri(hostname, project_slug)
         | 
| 13 | 
            +
                "#{hostname}/api/cli/v1/projects/#{project_slug}/compose_file"
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              def validate_compose_file_uri(hostname, project_slug)
         | 
| 17 | 
            +
                "#{compose_files_uri(hostname, project_slug)}/validate"
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              def deployments_uri(hostname, project_slug)
         | 
| 21 | 
            +
                "#{hostname}/api/cli/v1/projects/#{project_slug}/deployments"
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
              def deployment_uri(hostname, project_slug, deployment_id)
         | 
| 25 | 
            +
                "#{hostname}/api/cli/v1/projects/#{project_slug}/deployments/#{deployment_id}"
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
              def activity_items_uri(hostname, project_slug, deployment_id)
         | 
| 29 | 
            +
                "#{hostname}/api/cli/v1/projects/#{project_slug}/deployments/#{deployment_id}/activity_items"
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
              def deploy_containers_uri(hostname, project_slug, deployment_id)
         | 
| 33 | 
            +
                "#{hostname}/api/cli/v1/projects/#{project_slug}/deployments/#{deployment_id}/deploy_containers"
         | 
| 34 | 
            +
              end
         | 
| 11 35 | 
             
            end
         | 
| @@ -3,11 +3,30 @@ | |
| 3 3 | 
             
            require 'net/http'
         | 
| 4 4 | 
             
            require 'json'
         | 
| 5 5 | 
             
            require 'uffizzi/config_file'
         | 
| 6 | 
            +
            require 'uffizzi/response_helper'
         | 
| 6 7 |  | 
| 7 8 | 
             
            module Uffizzi
         | 
| 8 9 | 
             
              class HttpClient
         | 
| 9 10 | 
             
                class << self
         | 
| 10 | 
            -
                  def  | 
| 11 | 
            +
                  def make_get_request(request_uri, cookies_required = true)
         | 
| 12 | 
            +
                    make_request(:get, request_uri, cookies_required)
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  def make_post_request(request_uri, params = {}, cookies_required = true)
         | 
| 16 | 
            +
                    make_request(:post, request_uri, cookies_required, params)
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                  def make_put_request(request_uri, cookies_required = true)
         | 
| 20 | 
            +
                    make_request(:put, request_uri, cookies_required)
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  def make_delete_request(request_uri, cookies_required = true)
         | 
| 24 | 
            +
                    make_request(:delete, request_uri, cookies_required)
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                  private
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                  def make_request(method, request_uri, require_cookies, params = {})
         | 
| 11 30 | 
             
                    uri = URI(request_uri)
         | 
| 12 31 | 
             
                    use_ssl = request_uri.start_with?('https')
         | 
| 13 32 |  | 
| @@ -24,8 +43,6 @@ module Uffizzi | |
| 24 43 | 
             
                    response
         | 
| 25 44 | 
             
                  end
         | 
| 26 45 |  | 
| 27 | 
            -
                  private
         | 
| 28 | 
            -
             | 
| 29 46 | 
             
                  def build_request(uri, params, method, require_cookies)
         | 
| 30 47 | 
             
                    headers = { 'Content-Type' => 'application/json' }
         | 
| 31 48 | 
             
                    request = case method
         | 
| @@ -45,6 +62,7 @@ module Uffizzi | |
| 45 62 | 
             
                    if ConfigFile.exists? && ConfigFile.option_exists?(:basic_auth_user) && ConfigFile.option_exists?(:basic_auth_password)
         | 
| 46 63 | 
             
                      request.basic_auth(ConfigFile.read_option(:basic_auth_user), ConfigFile.read_option(:basic_auth_password))
         | 
| 47 64 | 
             
                    end
         | 
| 65 | 
            +
             | 
| 48 66 | 
             
                    request
         | 
| 49 67 | 
             
                  end
         | 
| 50 68 | 
             
                end
         | 
    
        data/lib/uffizzi/config_file.rb
    CHANGED
    
    | @@ -23,22 +23,21 @@ module Uffizzi | |
| 23 23 |  | 
| 24 24 | 
             
                  def read_option(option)
         | 
| 25 25 | 
             
                    data = read
         | 
| 26 | 
            -
                    return nil  | 
| 26 | 
            +
                    return nil unless data.is_a?(Hash)
         | 
| 27 27 |  | 
| 28 | 
            -
                    puts "The option #{option} doesn't exist in config file" if data[option].nil?
         | 
| 29 28 | 
             
                    data[option]
         | 
| 30 29 | 
             
                  end
         | 
| 31 30 |  | 
| 32 31 | 
             
                  def option_exists?(option)
         | 
| 33 32 | 
             
                    data = read
         | 
| 34 | 
            -
                    return false  | 
| 33 | 
            +
                    return false unless data.is_a?(Hash)
         | 
| 35 34 |  | 
| 36 35 | 
             
                    data.key?(option)
         | 
| 37 36 | 
             
                  end
         | 
| 38 37 |  | 
| 39 38 | 
             
                  def write_option(key, value)
         | 
| 40 39 | 
             
                    data = exists? ? read : {}
         | 
| 41 | 
            -
                    return nil  | 
| 40 | 
            +
                    return nil unless data.is_a?(Hash)
         | 
| 42 41 |  | 
| 43 42 | 
             
                    data[key] = value
         | 
| 44 43 | 
             
                    write(data.to_json)
         | 
| @@ -46,7 +45,7 @@ module Uffizzi | |
| 46 45 |  | 
| 47 46 | 
             
                  def delete_option(key)
         | 
| 48 47 | 
             
                    data = read
         | 
| 49 | 
            -
                    return nil  | 
| 48 | 
            +
                    return nil unless data.is_a?(Hash)
         | 
| 50 49 |  | 
| 51 50 | 
             
                    new_data = data.except(key)
         | 
| 52 51 | 
             
                    write(new_data.to_json)
         | 
| @@ -58,11 +57,16 @@ module Uffizzi | |
| 58 57 |  | 
| 59 58 | 
             
                  def list
         | 
| 60 59 | 
             
                    data = read
         | 
| 61 | 
            -
                    return nil  | 
| 60 | 
            +
                    return nil unless data.is_a?(Hash)
         | 
| 62 61 |  | 
| 63 | 
            -
                    data. | 
| 64 | 
            -
                       | 
| 62 | 
            +
                    content = data.reduce('') do |acc, pair|
         | 
| 63 | 
            +
                      property, value = pair
         | 
| 64 | 
            +
                      "#{acc}#{property} - #{value}\n"
         | 
| 65 65 | 
             
                    end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                    Uffizzi.ui.say(content)
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                    data
         | 
| 66 70 | 
             
                  end
         | 
| 67 71 |  | 
| 68 72 | 
             
                  private
         | 
| @@ -70,9 +74,11 @@ module Uffizzi | |
| 70 74 | 
             
                  def read
         | 
| 71 75 | 
             
                    JSON.parse(File.read(CONFIG_PATH), symbolize_names: true)
         | 
| 72 76 | 
             
                  rescue Errno::ENOENT => e
         | 
| 73 | 
            -
                     | 
| 77 | 
            +
                    Uffizzi.ui.say(e)
         | 
| 78 | 
            +
                    nil
         | 
| 74 79 | 
             
                  rescue JSON::ParserError
         | 
| 75 | 
            -
                     | 
| 80 | 
            +
                    Uffizzi.ui.say('Config file is in incorrect format')
         | 
| 81 | 
            +
                    nil
         | 
| 76 82 | 
             
                  end
         | 
| 77 83 |  | 
| 78 84 | 
             
                  def write(data)
         | 
| @@ -92,9 +98,7 @@ module Uffizzi | |
| 92 98 | 
             
                  def create_file
         | 
| 93 99 | 
             
                    dir = File.dirname(CONFIG_PATH)
         | 
| 94 100 |  | 
| 95 | 
            -
                    unless File.directory?(dir)
         | 
| 96 | 
            -
                      FileUtils.mkdir_p(dir)
         | 
| 97 | 
            -
                    end
         | 
| 101 | 
            +
                    FileUtils.mkdir_p(dir) unless File.directory?(dir)
         | 
| 98 102 |  | 
| 99 103 | 
             
                    File.new(CONFIG_PATH, 'w')
         | 
| 100 104 | 
             
                  end
         | 
| @@ -22,6 +22,30 @@ module Uffizzi | |
| 22 22 | 
             
                  def no_content?(response)
         | 
| 23 23 | 
             
                    response[:code] == Net::HTTPNoContent
         | 
| 24 24 | 
             
                  end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  def ok?(response)
         | 
| 27 | 
            +
                    response[:code] == Net::HTTPOK
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  def handle_failed_response(response)
         | 
| 31 | 
            +
                    print_errors(response[:body][:errors])
         | 
| 32 | 
            +
                  end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                  def handle_invalid_compose_response(response)
         | 
| 35 | 
            +
                    print_errors(response[:body][:compose_file][:payload][:errors])
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  private
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  def print_errors(errors)
         | 
| 41 | 
            +
                    errors.each_key do |key|
         | 
| 42 | 
            +
                      if errors[key].is_a?(Array)
         | 
| 43 | 
            +
                        errors[key].each { |error_message| Uffizzi.ui.say(error_message) }
         | 
| 44 | 
            +
                      else
         | 
| 45 | 
            +
                        Uffizzi.ui.say(errors[key])
         | 
| 46 | 
            +
                      end
         | 
| 47 | 
            +
                    end
         | 
| 48 | 
            +
                  end
         | 
| 25 49 | 
             
                end
         | 
| 26 50 | 
             
              end
         | 
| 27 51 | 
             
            end
         | 
| @@ -0,0 +1,102 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'psych'
         | 
| 4 | 
            +
            require 'pathname'
         | 
| 5 | 
            +
            require 'base64'
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            class ComposeFileService
         | 
| 8 | 
            +
              class << self
         | 
| 9 | 
            +
                def parse(compose_content, compose_file_path)
         | 
| 10 | 
            +
                  compose_data = parse_compose_content_to_object(compose_content)
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  env_files = prepare_services_env_files(compose_data['services']).flatten.uniq
         | 
| 13 | 
            +
                  config_files = fetch_configs(compose_data['configs'])
         | 
| 14 | 
            +
                  prepare_dependencies(env_files, config_files, compose_file_path)
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                private
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                def prepare_dependencies(env_files, config_files, compose_file_path)
         | 
| 20 | 
            +
                  prepare_dependency_files_data(env_files + config_files, compose_file_path)
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                def prepare_dependency_files_data(dependency_files, compose_file_path)
         | 
| 24 | 
            +
                  dependency_files.map do |dependency_file|
         | 
| 25 | 
            +
                    dependency_file_data = Psych.load(File.read("#{compose_file_path}/#{dependency_file}"))
         | 
| 26 | 
            +
                    {
         | 
| 27 | 
            +
                      path: dependency_file,
         | 
| 28 | 
            +
                      source: dependency_file,
         | 
| 29 | 
            +
                      content: Base64.encode64(dependency_file_data),
         | 
| 30 | 
            +
                    }
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                def fetch_configs(configs_data)
         | 
| 35 | 
            +
                  return [] if configs_data.nil?
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  Uffizzi.ui.say("Unsupported type of #{:configs} option") unless configs_data.is_a?(Hash)
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                  configs = []
         | 
| 40 | 
            +
                  configs_data.each_pair do |config_name, config_data|
         | 
| 41 | 
            +
                    Uffizzi.ui.say("#{config_name} has an empty file") if config_data['file'].empty? || config_data['file'].nil?
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                    configs << prepare_file_path(config_data['file'])
         | 
| 44 | 
            +
                  end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                  configs
         | 
| 47 | 
            +
                end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                def prepare_file_path(file_path)
         | 
| 50 | 
            +
                  pathname = Pathname.new(file_path)
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                  pathname.cleanpath.to_s.strip.delete_prefix('/')
         | 
| 53 | 
            +
                end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                def parse_env_file(env_file)
         | 
| 56 | 
            +
                  case env_file
         | 
| 57 | 
            +
                  when String
         | 
| 58 | 
            +
                    Uffizzi.ui.say('env_file contains an empty value') if env_file.nil? || env_file.empty?
         | 
| 59 | 
            +
                    [prepare_file_path(env_file)]
         | 
| 60 | 
            +
                  when Array
         | 
| 61 | 
            +
                    Uffizzi.ui.say('env_file contains an empty value') if env_file.any? { |file| file.nil? || file.empty? }
         | 
| 62 | 
            +
                    env_file.map { |env_file_path| prepare_file_path(env_file_path) }
         | 
| 63 | 
            +
                  else
         | 
| 64 | 
            +
                    Uffizzi.ui.say("Unsupported type of #{:env_file} option")
         | 
| 65 | 
            +
                  end
         | 
| 66 | 
            +
                end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                def prepare_services_env_files(services)
         | 
| 69 | 
            +
                  return [] if services.nil?
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                  services.keys.map do |service|
         | 
| 72 | 
            +
                    service_env_files = prepare_service_env_files(services.fetch(service))
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                    service_env_files
         | 
| 75 | 
            +
                  end
         | 
| 76 | 
            +
                end
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                def prepare_service_env_files(service_data)
         | 
| 79 | 
            +
                  env_files_data = []
         | 
| 80 | 
            +
                  service_data.each_pair do |key, value|
         | 
| 81 | 
            +
                    key_sym = key.to_sym
         | 
| 82 | 
            +
                    if key_sym == :env_file
         | 
| 83 | 
            +
                      env_files_data << parse_env_file(value)
         | 
| 84 | 
            +
                    end
         | 
| 85 | 
            +
                  end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                  env_files_data
         | 
| 88 | 
            +
                end
         | 
| 89 | 
            +
             | 
| 90 | 
            +
                def parse_compose_content_to_object(compose_content)
         | 
| 91 | 
            +
                  begin
         | 
| 92 | 
            +
                    compose_data = Psych.safe_load(compose_content)
         | 
| 93 | 
            +
                  rescue Psych::SyntaxError
         | 
| 94 | 
            +
                    Uffizzi.ui.say('Invalid compose file')
         | 
| 95 | 
            +
                  end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                  Uffizzi.ui.say('Unsupported compose file') if compose_data.nil?
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                  compose_data
         | 
| 100 | 
            +
                end
         | 
| 101 | 
            +
              end
         | 
| 102 | 
            +
            end
         | 
| @@ -0,0 +1,48 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'psych'
         | 
| 4 | 
            +
            require 'pathname'
         | 
| 5 | 
            +
            require 'base64'
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            class EnvVariablesService
         | 
| 8 | 
            +
              class << self
         | 
| 9 | 
            +
                def substitute_env_variables(compose_file_data)
         | 
| 10 | 
            +
                  compose_file_data.gsub(/\$\{?([?:\-_A-Za-z0-9]+)\}?/) do |variable|
         | 
| 11 | 
            +
                    variable_content = variable.match(/[?:\-_A-Za-z0-9]+/).to_s
         | 
| 12 | 
            +
                    fetch_variable_value(variable_content)
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                private
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                def fetch_variable_value(variable_content)
         | 
| 19 | 
            +
                  variable_name = variable_content.match(/^[_A-Za-z0-9]+/).to_s
         | 
| 20 | 
            +
                  variable_value = ENV[variable_name]
         | 
| 21 | 
            +
                  return variable_value unless variable_value.nil?
         | 
| 22 | 
            +
                  return fetch_variable_default_value(variable_content) if variable_has_default_value?(variable_content)
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  error_message = if variable_has_error_message?(variable_content)
         | 
| 25 | 
            +
                    fetch_env_error_message(variable_content)
         | 
| 26 | 
            +
                  else
         | 
| 27 | 
            +
                    "Environment variable #{variable_name} doesn't exist"
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
                  raise StandardError.new(error_message)
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                def variable_has_default_value?(variable_content)
         | 
| 33 | 
            +
                  variable_content.include?('-')
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                def fetch_variable_default_value(variable_content)
         | 
| 37 | 
            +
                  variable_content.split('-', 2).last
         | 
| 38 | 
            +
                end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                def variable_has_error_message?(variable_content)
         | 
| 41 | 
            +
                  variable_content.include?('?')
         | 
| 42 | 
            +
                end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                def fetch_env_error_message(variable_content)
         | 
| 45 | 
            +
                  variable_content.split('?', 2).last
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
              end
         | 
| 48 | 
            +
            end
         | 
    
        data/lib/uffizzi/version.rb
    CHANGED