pups 1.0.3 → 1.1.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.
@@ -1,43 +1,45 @@
1
- class Pups::ReplaceCommand < Pups::Command
2
- attr_accessor :text, :from, :to, :filename, :direction, :global
1
+ # frozen_string_literal: true
3
2
 
4
- def self.from_hash(hash, params)
5
- replacer = new(params)
6
- replacer.from = guess_replace_type(hash["from"])
7
- replacer.to = guess_replace_type(hash["to"])
8
- replacer.text = File.read(hash["filename"])
9
- replacer.filename = hash["filename"]
10
- replacer.direction = hash["direction"].to_sym if hash["direction"]
11
- replacer.global = hash["global"].to_s == "true"
12
- replacer
13
- end
3
+ module Pups
4
+ class ReplaceCommand < Pups::Command
5
+ attr_accessor :text, :from, :to, :filename, :direction, :global
14
6
 
15
- def self.guess_replace_type(item)
16
- # evaling to get all the regex flags easily
17
- item[0] == "/" ? eval(item) : item
18
- end
7
+ def self.from_hash(hash, params)
8
+ replacer = new(params)
9
+ replacer.from = guess_replace_type(hash['from'])
10
+ replacer.to = guess_replace_type(hash['to'])
11
+ replacer.text = File.read(hash['filename'])
12
+ replacer.filename = hash['filename']
13
+ replacer.direction = hash['direction'].to_sym if hash['direction']
14
+ replacer.global = hash['global'].to_s == 'true'
15
+ replacer
16
+ end
19
17
 
20
- def initialize(params)
21
- @params = params
22
- end
18
+ def self.guess_replace_type(item)
19
+ # evaling to get all the regex flags easily
20
+ item[0] == '/' ? eval(item) : item
21
+ end
23
22
 
24
- def replaced_text
25
- new_to = to
26
- if String === to
27
- new_to = interpolate_params(to)
23
+ def initialize(params)
24
+ @params = params
28
25
  end
29
- if global
30
- text.gsub(from,new_to)
31
- elsif direction == :reverse
32
- index = text.rindex(from)
33
- text[0..index-1] << text[index..-1].sub(from,new_to)
34
- else
35
- text.sub(from,new_to)
26
+
27
+ def replaced_text
28
+ new_to = to
29
+ new_to = interpolate_params(to) if to.is_a?(String)
30
+ if global
31
+ text.gsub(from, new_to)
32
+ elsif direction == :reverse
33
+ index = text.rindex(from)
34
+ text[0..index - 1] << text[index..-1].sub(from, new_to)
35
+ else
36
+ text.sub(from, new_to)
37
+ end
36
38
  end
37
- end
38
39
 
39
- def run
40
- Pups.log.info("Replacing #{from.to_s} with #{to.to_s} in #{filename}")
41
- File.open(filename, "w"){|f| f.write replaced_text }
40
+ def run
41
+ Pups.log.info("Replacing #{from} with #{to} in #{filename}")
42
+ File.open(filename, 'w') { |f| f.write replaced_text }
43
+ end
42
44
  end
43
45
  end
data/lib/pups/runit.rb CHANGED
@@ -1,40 +1,39 @@
1
- class Pups::Runit
1
+ # frozen_string_literal: true
2
2
 
3
- attr_accessor :env, :exec, :cd, :name
3
+ module Pups
4
+ class Runit
5
+ attr_accessor :env, :exec, :cd, :name
4
6
 
7
+ def initialize(name)
8
+ @name = name
9
+ end
5
10
 
6
- def initialize(name)
7
- @name = name
8
- end
9
-
10
- def setup
11
- `mkdir -p /etc/service/#{name}`
12
- run = "/etc/service/#{name}/run"
13
- File.open(run, "w") do |f|
14
- f.write(run_script)
11
+ def setup
12
+ `mkdir -p /etc/service/#{name}`
13
+ run = "/etc/service/#{name}/run"
14
+ File.open(run, 'w') do |f|
15
+ f.write(run_script)
16
+ end
17
+ `chmod +x #{run}`
15
18
  end
16
- `chmod +x #{run}`
17
- end
18
19
 
19
- def run_script
20
- "#!/bin/bash
20
+ def run_script
21
+ "#!/bin/bash
21
22
  exec 2>&1
22
23
  #{env_script}
23
24
  #{cd_script}
24
25
  #{exec}
25
26
  "
26
- end
27
+ end
27
28
 
28
- def cd_script
29
- "cd #{@cd}" if @cd
30
- end
29
+ def cd_script
30
+ "cd #{@cd}" if @cd
31
+ end
31
32
 
32
- def env_script
33
- if @env
34
- @env.map do |k,v|
33
+ def env_script
34
+ @env&.map do |k, v|
35
35
  "export #{k}=#{v}"
36
- end.join("\n")
36
+ end&.join("\n")
37
37
  end
38
38
  end
39
-
40
39
  end
data/lib/pups/version.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Pups
2
- VERSION = "1.0.3"
4
+ VERSION = '1.1.0'
3
5
  end
data/pups.gemspec CHANGED
@@ -1,26 +1,31 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
5
  require 'pups/version'
5
6
 
6
7
  Gem::Specification.new do |spec|
7
- spec.name = "pups"
8
+ spec.name = 'pups'
8
9
  spec.version = Pups::VERSION
9
- spec.authors = ["Sam Saffron"]
10
- spec.email = ["sam.saffron@gmail.com"]
11
- spec.description = %q{Simple docker image creator}
12
- spec.summary = %q{Toolkit for orchestrating a composed docker image}
13
- spec.homepage = ""
14
- spec.license = "MIT"
10
+ spec.authors = ['Sam Saffron']
11
+ spec.email = ['sam.saffron@gmail.com']
12
+ spec.description = 'Simple docker image creator'
13
+ spec.summary = 'Toolkit for orchestrating a composed docker image'
14
+ spec.homepage = ''
15
+ spec.license = 'MIT'
15
16
 
16
- spec.files = `git ls-files`.split($/)
17
+ spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
17
18
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
19
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
- spec.require_paths = ["lib"]
20
+ spec.require_paths = ['lib']
20
21
 
21
- spec.add_development_dependency "bundler"
22
- spec.add_development_dependency "rake"
23
- spec.add_development_dependency "minitest"
24
- spec.add_development_dependency "guard"
25
- spec.add_development_dependency "guard-minitest"
22
+ spec.add_development_dependency 'bundler'
23
+ spec.add_development_dependency 'guard'
24
+ spec.add_development_dependency 'guard-minitest'
25
+ spec.add_development_dependency 'minitest'
26
+ spec.add_development_dependency 'rake'
27
+ spec.add_development_dependency 'rubocop'
28
+ spec.add_development_dependency 'rubocop-discourse'
29
+ spec.add_development_dependency 'rubocop-minitest'
30
+ spec.add_development_dependency 'rubocop-rake'
26
31
  end
data/test/cli_test.rb ADDED
@@ -0,0 +1,117 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+ require 'tempfile'
5
+ require 'stringio'
6
+
7
+ module Pups
8
+ class CliTest < MiniTest::Test
9
+ def test_cli_option_parsing_stdin
10
+ options = Cli.parse_args(['--stdin'])
11
+ assert_equal(true, options[:stdin])
12
+ end
13
+
14
+ def test_cli_option_parsing_none
15
+ options = Cli.parse_args([])
16
+ assert_nil(options[:stdin])
17
+ end
18
+
19
+ def test_cli_read_config_from_file
20
+ # for testing output
21
+ f = Tempfile.new('test_output')
22
+ f.close
23
+
24
+ # for testing input
25
+ cf = Tempfile.new('test_config')
26
+ cf.puts <<~YAML
27
+ params:
28
+ run: #{f.path}
29
+ run:
30
+ - exec: echo hello world >> #{f.path}
31
+ YAML
32
+ cf.close
33
+
34
+ Cli.run([cf.path])
35
+ assert_equal('hello world', File.read(f.path).strip)
36
+ end
37
+
38
+ def test_cli_ignore_config_element
39
+ # for testing output
40
+ f = Tempfile.new('test_output')
41
+ f.close
42
+
43
+ # for testing input
44
+ cf = Tempfile.new('test_config')
45
+ cf.puts <<~YAML
46
+ env:
47
+ MY_IGNORED_VAR: a_word
48
+ params:
49
+ a_param_var: another_word
50
+ run:
51
+ - exec: echo repeating $MY_IGNORED_VAR and also $a_param_var >> #{f.path}
52
+ YAML
53
+ cf.close
54
+
55
+ Cli.run(["--ignore", "env,params", cf.path])
56
+ assert_equal('repeating and also', File.read(f.path).strip)
57
+ end
58
+
59
+ def test_cli_gen_docker_run_args_ignores_other_config
60
+ # When generating the docker run arguments it should ignore other template configuration
61
+ # like 'run' directives.
62
+
63
+ # for testing output
64
+ f = Tempfile.new("test_output")
65
+ f.close
66
+
67
+ # for testing input
68
+ cf = Tempfile.new("test_config")
69
+ cf.puts <<~YAML
70
+ env:
71
+ foo: 1
72
+ bar: 5
73
+ baz: 'hello_{{spam}}'
74
+ env_template:
75
+ spam: 'eggs'
76
+ config: my_app
77
+ params:
78
+ run: #{f.path}
79
+ run:
80
+ - exec: echo hello world >> #{f.path}
81
+ expose:
82
+ - "2222:22"
83
+ - "127.0.0.1:20080:80"
84
+ - 5555
85
+ volumes:
86
+ - volume:
87
+ host: /var/discourse/shared
88
+ guest: /shared
89
+ - volume:
90
+ host: /bar
91
+ guest: /baz
92
+ links:
93
+ - link:
94
+ name: postgres
95
+ alias: postgres
96
+ - link:
97
+ name: foo
98
+ alias: bar
99
+ labels:
100
+ monitor: "true"
101
+ app_name: "{{config}}_discourse"
102
+ YAML
103
+ cf.close
104
+
105
+ expected = []
106
+ expected << "--env foo=1 --env bar=5 --env baz=hello_eggs"
107
+ expected << "--publish 2222:22 --publish 127.0.0.1:20080:80 --expose 5555"
108
+ expected << "--volume /var/discourse/shared:/shared --volume /bar:/baz"
109
+ expected << "--link postgres:postgres --link foo:bar"
110
+ expected << "--label monitor=true --label app_name=my_app_discourse"
111
+ expected.sort!
112
+
113
+ assert_equal("", File.read(f.path).strip)
114
+ assert_output(expected.join(" ")) { Cli.run(["--gen-docker-run-args", cf.path]) }
115
+ end
116
+ end
117
+ end
data/test/config_test.rb CHANGED
@@ -1,55 +1,217 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
  require 'tempfile'
3
5
 
4
6
  module Pups
5
7
  class ConfigTest < MiniTest::Test
6
-
7
8
  def test_config_from_env
8
- ENV["HELLO"] = "world"
9
+ ENV['HELLO'] = 'world'
9
10
  config = Config.new({})
10
- assert_equal("world", config.params["$ENV_HELLO"])
11
+ assert_equal('world', config.params['$ENV_HELLO'])
11
12
  end
12
13
 
13
- def test_integration
14
+ def test_env_param
15
+ ENV['FOO'] = 'BAR'
16
+ config = <<~YAML
17
+ env:
18
+ BAR: baz
19
+ hello: WORLD
20
+ one: 1
21
+ YAML
14
22
 
15
- f = Tempfile.new("test")
16
- f.close
23
+ config = Config.new(YAML.safe_load(config))
24
+ %w[BAR hello one].each { |e| ENV.delete(e) }
25
+ assert_equal('BAR', config.params['$ENV_FOO'])
26
+ assert_equal('baz', config.params['$ENV_BAR'])
27
+ assert_equal('WORLD', config.params['$ENV_hello'])
28
+ assert_equal('1', config.params['$ENV_one'])
29
+ end
30
+
31
+ def test_env_with_template
32
+ ENV['FOO'] = 'BAR'
33
+ config = <<~YAML
34
+ env:
35
+ greeting: "{{hello}}, {{planet}}!"
36
+ one: 1
37
+ other: "where are we on {{planet}}?"
38
+ env_template:
39
+ planet: pluto
40
+ hello: hola
41
+ YAML
42
+ config_hash = YAML.safe_load(config)
43
+
44
+ config = Config.new(config_hash)
45
+ %w[greeting one other].each { |e| ENV.delete(e) }
46
+ assert_equal('hola, pluto!', config.params['$ENV_greeting'])
47
+ assert_equal('1', config.params['$ENV_one'])
48
+ assert_equal('BAR', config.params['$ENV_FOO'])
49
+ assert_equal('where are we on pluto?', config.params['$ENV_other'])
50
+ end
51
+
52
+ def test_label_with_template
53
+ ENV["FOO"] = "BAR"
54
+ config = <<~YAML
55
+ env:
56
+ greeting: "{{hello}}, {{planet}}!"
57
+ one: 1
58
+ other: "where are we on {{planet}}?"
59
+ env_template:
60
+ planet: pluto
61
+ hello: hola
62
+ config: various
63
+ labels:
64
+ app_name: "{{config}}_discourse"
65
+ YAML
66
+ config_hash = YAML.load(config)
67
+
68
+ config = Config.new(config_hash)
69
+ %w[greeting one other].each { |e| ENV.delete(e) }
70
+ assert_equal("various_discourse", config.config['labels']['app_name'])
71
+ end
72
+
73
+ def test_env_with_ENV_templated_variable
74
+ ENV['env_template_config'] = 'my_application'
75
+ config = <<~YAML
76
+ env:
77
+ greeting: "{{hello}}, {{planet}}!"
78
+ one: 1
79
+ other: "building {{config}}"
80
+ env_template:
81
+ planet: pluto
82
+ hello: hola
83
+ YAML
84
+ config_hash = YAML.safe_load(config)
85
+
86
+ config = Config.new(config_hash)
87
+ %w[greeting one other].each { |e| ENV.delete(e) }
88
+ assert_equal('hola, pluto!', config.params['$ENV_greeting'])
89
+ assert_equal('1', config.params['$ENV_one'])
90
+ assert_equal('building my_application', config.params['$ENV_other'])
91
+ ENV["env_template_config"] = nil
92
+ end
17
93
 
18
- config = <<YAML
19
- params:
20
- run: #{f.path}
21
- run:
22
- - exec: echo hello world >> #{f.path}
23
- YAML
94
+ def test_integration
95
+ f = Tempfile.new('test')
96
+ f.close
24
97
 
25
- Config.new(YAML.load(config)).run
26
- assert_equal("hello world", File.read(f.path).strip)
98
+ config = <<~YAML
99
+ env:
100
+ PLANET: world
101
+ params:
102
+ run: #{f.path}
103
+ greeting: hello
104
+ run:
105
+ - exec: echo $greeting $PLANET >> #{f.path}
106
+ YAML
27
107
 
108
+ Config.new(YAML.safe_load(config)).run
109
+ ENV.delete('PLANET')
110
+ assert_equal('hello world', File.read(f.path).strip)
28
111
  ensure
29
112
  f.unlink
30
113
  end
31
114
 
32
115
  def test_hooks
33
- yaml = <<YAML
34
- run:
35
- - exec: 1
36
- - exec:
37
- hook: middle
38
- cmd: 2
39
- - exec: 3
40
- hooks:
41
- after_middle:
42
- - exec: 2.1
43
- before_middle:
44
- - exec: 1.9
45
- YAML
116
+ yaml = <<~YAML
117
+ run:
118
+ - exec: 1
119
+ - exec:
120
+ hook: middle
121
+ cmd: 2
122
+ - exec: 3
123
+ hooks:
124
+ after_middle:
125
+ - exec: 2.1
126
+ before_middle:
127
+ - exec: 1.9
128
+ YAML
46
129
 
47
130
  config = Config.load_config(yaml).config
48
- assert_equal({ "exec" => 1.9 }, config["run"][1])
49
- assert_equal({ "exec" => 2.1 }, config["run"][3])
131
+ assert_equal({ 'exec' => 1.9 }, config['run'][1])
132
+ assert_equal({ 'exec' => 2.1 }, config['run'][3])
133
+ end
134
+
135
+ def test_ignored_elements
136
+ f = Tempfile.new('test')
137
+ f.close
138
+
139
+ yaml = <<~YAML
140
+ env:
141
+ PLANET: world
142
+ params:
143
+ greeting: hello
144
+ run:
145
+ - exec: 1
146
+ - exec:
147
+ hook: middle
148
+ cmd: 2
149
+ - exec: 3
150
+ - exec: echo $greeting $PLANET >> #{f.path}
151
+ hooks:
152
+ after_middle:
153
+ - exec: 2.1
154
+ before_middle:
155
+ - exec: 1.9
156
+ YAML
50
157
 
158
+ conf = Config.load_config(yaml, %w[hooks params])
159
+ config = conf.config
160
+ assert_equal({ 'exec' => 1 }, config['run'][0])
161
+ assert_equal({ 'exec' => { 'hook' => 'middle', 'cmd' => 2 } }, config['run'][1])
162
+ assert_equal({ 'exec' => 3 }, config['run'][2])
163
+ assert_equal({ 'exec' => "echo $greeting $PLANET >> #{f.path}" }, config['run'][3])
51
164
 
165
+ # $greet from params will be an empty var as it was ignored
166
+ conf.run
167
+ ENV.delete('PLANET')
168
+ assert_equal('world', File.read(f.path).strip)
169
+ end
170
+
171
+ def test_generate_docker_run_arguments
172
+ yaml = <<~YAML
173
+ env:
174
+ foo: 1
175
+ bar: 2
176
+ baz: 'hello_{{spam}}'
177
+ env_template:
178
+ spam: 'eggs'
179
+ config: my_app
180
+ expose:
181
+ - "2222:22"
182
+ - "127.0.0.1:20080:80"
183
+ - 5555
184
+ volumes:
185
+ - volume:
186
+ host: /var/discourse/shared
187
+ guest: /shared
188
+ - volume:
189
+ host: /bar
190
+ guest: /baz
191
+ links:
192
+ - link:
193
+ name: postgres
194
+ alias: postgres
195
+ - link:
196
+ name: foo
197
+ alias: bar
198
+ labels:
199
+ monitor: "true"
200
+ app_name: "{{config}}_discourse"
201
+ YAML
202
+
203
+ config = Config.load_config(yaml)
204
+ args = config.generate_docker_run_arguments
205
+
206
+ expected = []
207
+ expected << "--env foo=1 --env bar=2 --env baz=hello_eggs"
208
+ expected << "--publish 2222:22 --publish 127.0.0.1:20080:80 --expose 5555"
209
+ expected << "--volume /var/discourse/shared:/shared --volume /bar:/baz"
210
+ expected << "--link postgres:postgres --link foo:bar"
211
+ expected << "--label monitor=true --label app_name=my_app_discourse"
212
+ expected.sort!
213
+
214
+ assert_equal(expected.join(" "), args)
52
215
  end
53
216
  end
54
217
  end
55
-