uffizzi-cli 1.0.3 → 1.0.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c73f738c3d7c7c9773f36b0c500300e91faf276e7f939ecdfb596a0dc5546145
4
- data.tar.gz: dda472028a13e9504fb0b387863eb16892ed2d3b01efb1ee7f99f0fd1290685c
3
+ metadata.gz: 5aa0242e35791e35a51a850316bb18a97f1651aa345c64ee05264cb6b7faa702
4
+ data.tar.gz: bc9a8c8176c2969edf8728be715a0d45c38dab6a3d0e6da37c8022e04d9e8e24
5
5
  SHA512:
6
- metadata.gz: 8f50a0fc27ea11fbc497968a9861679b24b67e41b430f518eae6c59be9b9fc698c7142213a7c98d3ffe323ce71d5c9dc5eac19031ee9e55dc2d4628abe2ed4e6
7
- data.tar.gz: e7980d0ff7b013e1e7aec8872afcd20c50570689dd43d03720d6a096138a0894ce6932f5166ce564befd901d5553bbb80fdb5c8667f7a1605e6685b5179ae28e
6
+ metadata.gz: 993d29e07d6fe739cd3ab82383a948ed2d251f7b00662b02b87cd3a9b1b556ee2e1ed16f224f857ce0689ac64b84d02b74aa711f24f477d546d1f13c378938a1
7
+ data.tar.gz: d91befdb081561d8395800f672918518397a70734abc3ff1ec2b57faa0180063f808722afc14de85e056507972d97eb4ef774614d1dd72a54311f5f34629abf0
@@ -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
@@ -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.4'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
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.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josh Thurman
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2022-10-17 00:00:00.000000000 Z
12
+ date: 2022-10-18 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