uffizzi-cli 0.1.3 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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