pups 1.0.0 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,37 +1,37 @@
1
- class Pups::FileCommand < Pups::Command
2
- attr_accessor :path, :contents, :params, :type, :chmod
1
+ # frozen_string_literal: true
3
2
 
4
- def self.from_hash(hash, params)
5
- command = new
6
- command.path = hash["path"]
7
- command.contents = hash["contents"]
8
- command.chmod = hash["chmod"]
9
- command.params = params
3
+ module Pups
4
+ class FileCommand < Pups::Command
5
+ attr_accessor :path, :contents, :params, :type, :chmod, :chown
10
6
 
11
- command
12
- end
7
+ def self.from_hash(hash, params)
8
+ command = new
9
+ command.path = hash['path']
10
+ command.contents = hash['contents']
11
+ command.chmod = hash['chmod']
12
+ command.chown = hash['chown']
13
+ command.params = params
13
14
 
14
- def initialize
15
- @params = {}
16
- @type = :bash
17
- end
15
+ command
16
+ end
18
17
 
19
- def params=(p)
20
- @params = p
21
- end
18
+ def initialize
19
+ @params = {}
20
+ @type = :bash
21
+ end
22
22
 
23
- def run
24
- path = interpolate_params(@path)
23
+ attr_writer :params
25
24
 
26
- `mkdir -p #{File.dirname(path)}`
27
- File.open(path, "w") do |f|
28
- f.write(interpolate_params(contents))
29
- end
30
- if @chmod
31
- `chmod #{@chmod} #{path}`
25
+ def run
26
+ path = interpolate_params(@path)
27
+
28
+ `mkdir -p #{File.dirname(path)}`
29
+ File.open(path, 'w') do |f|
30
+ f.write(interpolate_params(contents))
31
+ end
32
+ `chmod #{@chmod} #{path}` if @chmod
33
+ `chown #{@chown} #{path}` if @chown
34
+ Pups.log.info("File > #{path} chmod: #{@chmod} chown: #{@chown}")
32
35
  end
33
- Pups.log.info("File > #{path} chmod: #{@chmod}")
34
36
  end
35
-
36
37
  end
37
-
@@ -1,48 +1,50 @@
1
- class Pups::MergeCommand < Pups::Command
2
- attr_reader :filename
3
- attr_reader :merge_hash
4
-
5
- def self.from_str(command, params)
6
- new(command,params)
7
- end
8
-
9
- def self.parse_command(command)
10
- split = command.split(" ")
11
- raise ArgumentError.new("Invalid merge command #{command}") unless split[-1][0] == "$"
12
-
13
- [split[0..-2].join(" ") , split[-1][1..-1]]
14
- end
15
-
16
- def initialize(command, params)
17
- @params = params
18
-
19
- filename, target_param = Pups::MergeCommand.parse_command(command)
20
- @filename = interpolate_params(filename)
21
- @merge_hash = params[target_param]
22
- end
23
-
24
- def run
25
- merged = self.class.deep_merge(YAML.load_file(@filename), @merge_hash)
26
- File.open(@filename,"w"){|f| f.write(merged.to_yaml) }
27
- Pups.log.info("Merge: #{@filename} with: \n#{@merge_hash.inspect}")
1
+ # frozen_string_literal: true
2
+
3
+ module Pups
4
+ class MergeCommand < Pups::Command
5
+ attr_reader :filename, :merge_hash
6
+
7
+ def self.from_str(command, params)
8
+ new(command, params)
9
+ end
10
+
11
+ def self.parse_command(command)
12
+ split = command.split(' ')
13
+ raise ArgumentError, "Invalid merge command #{command}" unless split[-1][0] == '$'
14
+
15
+ [split[0..-2].join(' '), split[-1][1..-1]]
16
+ end
17
+
18
+ def initialize(command, params)
19
+ @params = params
20
+
21
+ filename, target_param = Pups::MergeCommand.parse_command(command)
22
+ @filename = interpolate_params(filename)
23
+ @merge_hash = params[target_param]
24
+ end
25
+
26
+ def run
27
+ merged = self.class.deep_merge(YAML.load_file(@filename), @merge_hash)
28
+ File.open(@filename, 'w') { |f| f.write(merged.to_yaml) }
29
+ Pups.log.info("Merge: #{@filename} with: \n#{@merge_hash.inspect}")
30
+ end
31
+
32
+ def self.deep_merge(first, second, *args)
33
+ args ||= []
34
+ merge_arrays = args.include? :merge_arrays
35
+
36
+ merger = proc { |_key, v1, v2|
37
+ if v1.is_a?(Hash) && v2.is_a?(Hash)
38
+ v1.merge(v2, &merger)
39
+ elsif v1.is_a?(Array) && v2.is_a?(Array)
40
+ merge_arrays ? v1 + v2 : v2
41
+ elsif v2.is_a?(NilClass)
42
+ v1
43
+ else
44
+ v2
45
+ end
46
+ }
47
+ first.merge(second, &merger)
48
+ end
28
49
  end
29
-
30
- def self.deep_merge(first,second, *args)
31
- args ||= []
32
- merge_arrays = args.include? :merge_arrays
33
-
34
- merger = proc { |key, v1, v2|
35
- if Hash === v1 && Hash === v2
36
- v1.merge(v2, &merger)
37
- elsif Array === v1 && Array === v2
38
- merge_arrays ? v1 + v2 : v2
39
- elsif NilClass === v2
40
- v1
41
- else
42
- v2
43
- end
44
- }
45
- first.merge(second, &merger)
46
- end
47
-
48
50
  end
@@ -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.0"
4
+ VERSION = '1.1.1'
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{Process orchestrator}
12
- spec.summary = %q{Process orchestrator}
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", "~> 1.3"
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