uffizzi-cli 1.0.3 → 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c73f738c3d7c7c9773f36b0c500300e91faf276e7f939ecdfb596a0dc5546145
4
- data.tar.gz: dda472028a13e9504fb0b387863eb16892ed2d3b01efb1ee7f99f0fd1290685c
3
+ metadata.gz: 52ed7b3048478db9710fad59d37f003adc38778d9f7dba20bf6cfa9a050f940a
4
+ data.tar.gz: c38c9a39c5f93f541937398bcfdd1e3b41465cc91da4be0cf2f2f6f6a353005b
5
5
  SHA512:
6
- metadata.gz: 8f50a0fc27ea11fbc497968a9861679b24b67e41b430f518eae6c59be9b9fc698c7142213a7c98d3ffe323ce71d5c9dc5eac19031ee9e55dc2d4628abe2ed4e6
7
- data.tar.gz: e7980d0ff7b013e1e7aec8872afcd20c50570689dd43d03720d6a096138a0894ce6932f5166ce564befd901d5553bbb80fdb5c8667f7a1605e6685b5179ae28e
6
+ metadata.gz: 18460c1f129c98588efe256fcfa0584521098d81f3d4473573859e78e08bfddce15e66ae7c3b541611dc5ee2ae4c96c96f601cb09ab334700202a6b8cc53f82e
7
+ data.tar.gz: 628a6f2448ce1545e49274d486c7c0b52eed61b51d05f170ea6847417cb24a8e732a4c838bc3842c93cc52d8dd24d6996ba337a307f841388beed820cf503b03
@@ -70,9 +70,8 @@ module Uffizzi
70
70
  logs = response[:body][:logs] || []
71
71
  return Uffizzi.ui.say("The service '#{container_name}' has no logs") if logs.empty?
72
72
 
73
- logs.each do |log|
74
- Uffizzi.ui.say(log)
75
- end
73
+ logs_columns = logs.map { |log| [log[:timestamp], log[:payload]] }
74
+ Uffizzi.ui.print_table(logs_columns)
76
75
  end
77
76
  end
78
77
  end
@@ -3,30 +3,45 @@
3
3
  require 'psych'
4
4
  require 'pathname'
5
5
  require 'base64'
6
+ require 'minitar'
7
+ require 'zlib'
8
+ require 'uffizzi/services/project_service'
9
+ require 'uffizzi/services/volume_parser_service'
6
10
 
7
11
  class ComposeFileService
12
+ MAX_HOST_VOLUME_GZIP_FILE_SIZE = 1024 * 900
13
+ DEPENDENCY_CONFIG_USE_KIND = :config_map
14
+ DEPENDENCY_VOLUME_USE_KIND = :volume
15
+
8
16
  class << self
9
- def parse(compose_content, compose_file_path)
17
+ def parse(compose_content, compose_file_dir)
10
18
  compose_data = parse_compose_content_to_object(compose_content)
11
19
 
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)
20
+ services = compose_data['services']
21
+ env_files_paths = prepare_env_files_paths(services).flatten.uniq
22
+ config_files_paths = prepare_config_files_paths(compose_data['configs'])
23
+ host_volumes_paths = prepare_host_volumes_paths(services)
24
+ prepare_dependencies(compose_file_dir, env_files_paths, config_files_paths, host_volumes_paths)
15
25
  end
16
26
 
17
27
  private
18
28
 
19
- def prepare_dependencies(env_files, config_files, compose_file_path)
20
- prepare_dependency_files_data(env_files + config_files, compose_file_path)
29
+ def prepare_dependencies(compose_file_dir, env_files_paths, config_files_paths, host_volumes_paths)
30
+ config_files_attrs = prepare_dependency_configs_files(env_files_paths + config_files_paths, compose_file_dir)
31
+ host_volumes_attrs = prepare_dependency_host_volumes_files(host_volumes_paths, compose_file_dir)
32
+
33
+ config_files_attrs + host_volumes_attrs
21
34
  end
22
35
 
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}"))
36
+ def prepare_dependency_configs_files(dependency_file_paths, compose_file_dir)
37
+ dependency_file_paths.map do |dependency_file_path|
38
+ dependency_file_content = Psych.load(File.read("#{compose_file_dir}/#{dependency_file_path}"))
39
+
26
40
  {
27
- path: dependency_file,
28
- source: dependency_file,
29
- content: Base64.encode64(dependency_file_data),
41
+ path: dependency_file_path,
42
+ source: dependency_file_path,
43
+ content: Base64.encode64(dependency_file_content),
44
+ use_kind: DEPENDENCY_CONFIG_USE_KIND,
30
45
  }
31
46
  end
32
47
  rescue Errno::ENOENT => e
@@ -34,7 +49,48 @@ class ComposeFileService
34
49
  raise Uffizzi::Error.new("The config file #{dependency_path} does not exist")
35
50
  end
36
51
 
37
- def fetch_configs(configs_data)
52
+ def prepare_dependency_host_volumes_files(dependency_file_paths, compose_file_dir)
53
+ base_dependency_paths = dependency_file_paths.map do |dependency_file_path|
54
+ dependency_pathname = Pathname.new(dependency_file_path)
55
+ next dependency_file_path if dependency_pathname.absolute?
56
+ next "#{compose_file_dir}/#{dependency_pathname.cleanpath}" if dependency_file_path.start_with?('./')
57
+ next "#{compose_file_dir}/#{dependency_pathname}" if dependency_file_path.start_with?('../')
58
+
59
+ raise Uffizzi::Error.new("Unsupported path #{dependency_pathname}")
60
+ end
61
+
62
+ base_dependency_paths.zip(dependency_file_paths).map do |base_dependency_path, dependency_file_path|
63
+ absolute_dependency_path = Pathname.new(base_dependency_path).realpath.to_s
64
+ dependency_file_content = prepare_host_volume_file_content(absolute_dependency_path)
65
+
66
+ {
67
+ path: absolute_dependency_path,
68
+ source: dependency_file_path,
69
+ content: dependency_file_content,
70
+ use_kind: DEPENDENCY_VOLUME_USE_KIND,
71
+ is_file: Pathname.new(absolute_dependency_path).file?,
72
+ }
73
+ end
74
+ rescue Errno::ENOENT => e
75
+ dependency_path = e.message.split('- ').last
76
+ raise Uffizzi::Error.new("No such file or directory: #{dependency_path}")
77
+ end
78
+
79
+ def prepare_host_volume_file_content(path)
80
+ tmp_tar_name = Base64.encode64(path)[0..20]
81
+ tmp_tar_path = "/tmp/#{tmp_tar_name}.tar.gz"
82
+
83
+ Minitar.pack(path, Zlib::GzipWriter.new(File.open(tmp_tar_path, 'wb')))
84
+ gzipped_file_size = Pathname.new(tmp_tar_path).size
85
+
86
+ if gzipped_file_size > MAX_HOST_VOLUME_GZIP_FILE_SIZE
87
+ Uffizzi.ui.say("File/Directory too big by path: #{path}. Gzipped tar archive size is #{gzipped_file_size}")
88
+ end
89
+
90
+ Base64.encode64(File.binread(tmp_tar_path))
91
+ end
92
+
93
+ def prepare_config_files_paths(configs_data)
38
94
  return [] if configs_data.nil?
39
95
 
40
96
  Uffizzi.ui.say("Unsupported type of #{:configs} option") unless configs_data.is_a?(Hash)
@@ -68,26 +124,16 @@ class ComposeFileService
68
124
  end
69
125
  end
70
126
 
71
- def prepare_services_env_files(services)
127
+ def prepare_env_files_paths(services)
72
128
  return [] if services.nil?
73
129
 
74
- services.keys.map do |service|
75
- service_env_files = prepare_service_env_files(services.fetch(service))
76
-
77
- service_env_files
78
- end
79
- end
80
-
81
- def prepare_service_env_files(service_data)
82
- env_files_data = []
83
- service_data.each_pair do |key, value|
84
- key_sym = key.to_sym
85
- if key_sym == :env_file
86
- env_files_data << parse_env_file(value)
87
- end
88
- end
89
-
90
- env_files_data
130
+ services
131
+ .values
132
+ .select { |s| s.has_key?('env_file') }
133
+ .map { |s| parse_env_file(s['env_file']) }
134
+ .flatten
135
+ .compact
136
+ .uniq
91
137
  end
92
138
 
93
139
  def parse_compose_content_to_object(compose_content)
@@ -101,5 +147,17 @@ class ComposeFileService
101
147
 
102
148
  compose_data
103
149
  end
150
+
151
+ def prepare_host_volumes_paths(services)
152
+ return [] if services.nil?
153
+
154
+ services
155
+ .values
156
+ .select { |s| s.has_key?('volumes') }
157
+ .map { |s| VolumeParserService.parse(s['volumes']) }
158
+ .flatten
159
+ .compact
160
+ .uniq
161
+ end
104
162
  end
105
163
  end
@@ -7,7 +7,9 @@ require 'base64'
7
7
  class EnvVariablesService
8
8
  class << self
9
9
  def substitute_env_variables(compose_file_data)
10
- compose_file_data.gsub(/\$\{?([?:\-_A-Za-z0-9]+)\}?/) do |variable|
10
+ compose_file_data.gsub(/\${1,2}\{?([?:\-_A-Za-z0-9]+)\}?/) do |variable|
11
+ next variable if variable.start_with?('$$')
12
+
11
13
  variable_content = variable.match(/[?:\-_A-Za-z0-9]+/).to_s
12
14
  fetch_variable_value(variable_content)
13
15
  end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ class VolumeParserService
4
+ class << self
5
+ def parse(volumes)
6
+ return [] if volumes.empty?
7
+
8
+ Uffizzi.ui.say("Volumes '#{volumes}' should be an array") unless volumes.is_a?(Array)
9
+
10
+ volumes.map { |volume| parse_volume(volume) }
11
+ end
12
+
13
+ private
14
+
15
+ def parse_volume(volume)
16
+ case volume
17
+ when String
18
+ process_short_syntax(volume)
19
+ when Hash
20
+ process_long_syntax(volume)
21
+ else
22
+ Uffizzi.ui.say("Unsupported type of '#{volumes}' option")
23
+ end
24
+ end
25
+
26
+ def process_short_syntax(volume_data)
27
+ path_part1, path_part2 = volume_data.split(':').map(&:strip)
28
+
29
+ path_part1 if host_volume?(path_part1, path_part2)
30
+ end
31
+
32
+ def process_long_syntax(volume_data)
33
+ source_path = volume_data['source'].to_s.strip
34
+ target_path = volume_data['target'].to_s.strip
35
+
36
+ source_path if host_volume?(source_path, target_path)
37
+ end
38
+
39
+ def host_volume?(source_path, target_path)
40
+ path?(source_path) && path?(target_path)
41
+ end
42
+
43
+ def path?(path)
44
+ path.to_s.start_with?('/', './', '../')
45
+ end
46
+ end
47
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Uffizzi
4
- VERSION = '1.0.3'
4
+ VERSION = '1.0.5'
5
5
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: uffizzi-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josh Thurman
8
8
  - Grayson Adkins
9
- autorequire:
9
+ autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2022-10-17 00:00:00.000000000 Z
12
+ date: 2022-11-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: awesome_print
@@ -25,6 +25,20 @@ dependencies:
25
25
  - - ">="
26
26
  - !ruby/object:Gem::Version
27
27
  version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: minitar
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
28
42
  - !ruby/object:Gem::Dependency
29
43
  name: thor
30
44
  requirement: !ruby/object:Gem::Requirement
@@ -109,6 +123,20 @@ dependencies:
109
123
  - - ">="
110
124
  - !ruby/object:Gem::Version
111
125
  version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: deepsort
128
+ requirement: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - "~>"
131
+ - !ruby/object:Gem::Version
132
+ version: 0.4.5
133
+ type: :development
134
+ prerelease: false
135
+ version_requirements: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - "~>"
138
+ - !ruby/object:Gem::Version
139
+ version: 0.4.5
112
140
  - !ruby/object:Gem::Dependency
113
141
  name: factory_bot
114
142
  requirement: !ruby/object:Gem::Requirement
@@ -123,6 +151,20 @@ dependencies:
123
151
  - - ">="
124
152
  - !ruby/object:Gem::Version
125
153
  version: '0'
154
+ - !ruby/object:Gem::Dependency
155
+ name: fakefs
156
+ requirement: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - ">="
159
+ - !ruby/object:Gem::Version
160
+ version: '0'
161
+ type: :development
162
+ prerelease: false
163
+ version_requirements: !ruby/object:Gem::Requirement
164
+ requirements:
165
+ - - ">="
166
+ - !ruby/object:Gem::Version
167
+ version: '0'
126
168
  - !ruby/object:Gem::Dependency
127
169
  name: faker
128
170
  requirement: !ruby/object:Gem::Requirement
@@ -347,6 +389,7 @@ files:
347
389
  - lib/uffizzi/services/env_variables_service.rb
348
390
  - lib/uffizzi/services/preview_service.rb
349
391
  - lib/uffizzi/services/project_service.rb
392
+ - lib/uffizzi/services/volume_parser_service.rb
350
393
  - lib/uffizzi/shell.rb
351
394
  - lib/uffizzi/version.rb
352
395
  - man/uffizzi
@@ -430,7 +473,7 @@ metadata:
430
473
  homepage_uri: https://uffizzi.com
431
474
  source_code_uri: https://github.com/UffizziCloud/uffizzi_cli
432
475
  changelog_uri: https://github.com/UffizziCloud/uffizzi_cli/blob/master/CHANGELOG.md
433
- post_install_message:
476
+ post_install_message:
434
477
  rdoc_options: []
435
478
  require_paths:
436
479
  - lib
@@ -445,8 +488,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
445
488
  - !ruby/object:Gem::Version
446
489
  version: '0'
447
490
  requirements: []
448
- rubygems_version: 3.3.7
449
- signing_key:
491
+ rubygems_version: 3.2.32
492
+ signing_key:
450
493
  specification_version: 4
451
494
  summary: uffizzi-cli
452
495
  test_files: []