minarai 0.0.1

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.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +41 -0
  5. data/.travis.yml +3 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +21 -0
  9. data/Rakefile +6 -0
  10. data/bin/minarai +5 -0
  11. data/examples/recipe_directory.yml +8 -0
  12. data/examples/recipe_erb.yml.erb +13 -0
  13. data/examples/recipe_file.yml +11 -0
  14. data/examples/recipe_git.yml +9 -0
  15. data/examples/recipe_homebrew.yml +6 -0
  16. data/examples/recipe_homebrew_cask.yml +6 -0
  17. data/examples/recipe_link.yml +4 -0
  18. data/examples/recipe_url_get.yml +4 -0
  19. data/examples/recipe_variable.yml +4 -0
  20. data/lib/minarai.rb +6 -0
  21. data/lib/minarai/action_builder.rb +47 -0
  22. data/lib/minarai/actions/base.rb +87 -0
  23. data/lib/minarai/actions/directory.rb +51 -0
  24. data/lib/minarai/actions/file.rb +85 -0
  25. data/lib/minarai/actions/git.rb +36 -0
  26. data/lib/minarai/actions/homebrew.rb +35 -0
  27. data/lib/minarai/actions/homebrew_cask.rb +35 -0
  28. data/lib/minarai/actions/link.rb +53 -0
  29. data/lib/minarai/actions/unknown.rb +26 -0
  30. data/lib/minarai/actions/url_get.rb +38 -0
  31. data/lib/minarai/command.rb +47 -0
  32. data/lib/minarai/errors/attribute_validation_error.rb +17 -0
  33. data/lib/minarai/errors/base.rb +6 -0
  34. data/lib/minarai/errors/invalid_action_type_error.rb +15 -0
  35. data/lib/minarai/errors/missing_recipe_path_error.rb +11 -0
  36. data/lib/minarai/loaders/base.rb +75 -0
  37. data/lib/minarai/loaders/recipe_loader.rb +39 -0
  38. data/lib/minarai/loaders/variable_loader.rb +14 -0
  39. data/lib/minarai/logger.rb +69 -0
  40. data/lib/minarai/recipe.rb +28 -0
  41. data/lib/minarai/runner.rb +22 -0
  42. data/lib/minarai/variable.rb +19 -0
  43. data/lib/minarai/version.rb +3 -0
  44. data/lib/validator/required_validator.rb +7 -0
  45. data/lib/validator/type_validator.rb +13 -0
  46. data/minarai.gemspec +30 -0
  47. data/spec/minarai/unit/action/base_spec.rb +26 -0
  48. data/spec/minarai/unit/action_builder_spec.rb +21 -0
  49. data/spec/minarai/unit/logger_spec.rb +18 -0
  50. data/spec/minarai/unit/variable_spec.rb +11 -0
  51. data/spec/spec_helper.rb +5 -0
  52. metadata +240 -0
@@ -0,0 +1,36 @@
1
+ require 'minarai/actions/base'
2
+
3
+ module Minarai
4
+ module Actions
5
+ class Git < Base
6
+ attribute :repository, required: true
7
+ attribute :destination, required: true
8
+
9
+ def run
10
+ clone
11
+ end
12
+
13
+ private
14
+
15
+ def complete?
16
+ has_git? && existed?
17
+ end
18
+
19
+ def clone
20
+ run_command("git clone #{repository} #{destination}")
21
+ end
22
+
23
+ def existed?
24
+ check_specific_command(:check_file_is_directory, destination)
25
+ end
26
+
27
+ def has_git?
28
+ check_command 'which git'
29
+ end
30
+
31
+ def name
32
+ super || "clone #{repository} to #{destination}"
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,35 @@
1
+ require 'minarai/actions/base'
2
+
3
+ module Minarai
4
+ module Actions
5
+ class Homebrew < Base
6
+ attribute :item, required: true
7
+
8
+ def run
9
+ install
10
+ end
11
+
12
+ private
13
+
14
+ def install
15
+ run_specific_command(:install_package, item)
16
+ end
17
+
18
+ def complete?
19
+ has_homebrew? && installed?
20
+ end
21
+
22
+ def installed?
23
+ check_specific_command(:check_package_is_installed, item)
24
+ end
25
+
26
+ def has_homebrew?
27
+ check_command 'which brew'
28
+ end
29
+
30
+ def name
31
+ super || "brew install #{item}"
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,35 @@
1
+ require 'minarai/actions/base'
2
+
3
+ module Minarai
4
+ module Actions
5
+ class HomebrewCask < Base
6
+ attribute :item, required: true
7
+
8
+ def run
9
+ install
10
+ end
11
+
12
+ private
13
+
14
+ def install
15
+ run_command "brew cask install #{item}"
16
+ end
17
+
18
+ def complete?
19
+ has_homebrew? && installed?
20
+ end
21
+
22
+ def installed?
23
+ check_command "/usr/local/bin/brew cask list -1 | grep -E '^#{item}$'"
24
+ end
25
+
26
+ def has_homebrew?
27
+ check_command 'which brew-cask'
28
+ end
29
+
30
+ def name
31
+ super || "brew cask install #{item}"
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,53 @@
1
+ require 'minarai/actions/base'
2
+
3
+ module Minarai
4
+ module Actions
5
+ class Link < Base
6
+ attribute :destination, required: true, type: String
7
+ attribute :source, required: true, type: String
8
+
9
+ def call
10
+ abort_with_runtime_error unless runnable?
11
+ super
12
+ end
13
+
14
+ def run
15
+ link
16
+ end
17
+
18
+ private
19
+
20
+ def link
21
+ run_specific_command(:link_file_to, destination, source)
22
+ end
23
+
24
+ def complete?
25
+ existed_file?
26
+ end
27
+
28
+ def readable_source?
29
+ !source.nil? && ::File.readable?(source)
30
+ end
31
+
32
+ def runnable?
33
+ readable_source?
34
+ end
35
+
36
+ def abort_with_runtime_error
37
+ Minarai::Logger.errorr(runtime_error) and abort
38
+ end
39
+
40
+ def runtime_error
41
+ Minarai::Errors::AttributeValidationError.new('source', 'is not readable file', name)
42
+ end
43
+
44
+ def existed_file?
45
+ check_specific_command(:check_file_is_linked_to, destination, source)
46
+ end
47
+
48
+ def name
49
+ super || "create symlink #{repository} to #{destination}"
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,26 @@
1
+ require 'minarai/actions/base'
2
+ require 'minarai/errors/invalid_action_type_error'
3
+
4
+ module Minarai
5
+ module Actions
6
+ class Unknown < Base
7
+ def run
8
+ # override
9
+ end
10
+
11
+ def error_messages
12
+ [Minarai::Errors::InvalidActionTypeError.new(name)]
13
+ end
14
+
15
+ private
16
+
17
+ def complete?
18
+ # override
19
+ end
20
+
21
+ def name
22
+ super || 'unknow action'
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,38 @@
1
+ require 'minarai/actions/base'
2
+
3
+ module Minarai
4
+ module Actions
5
+ class UrlGet < Base
6
+ attribute :source, required: true, type: String
7
+ attribute :destination, required: true, type: String
8
+
9
+ def run
10
+ url_get
11
+ end
12
+
13
+ private
14
+
15
+ def url_get
16
+ run_command("curl -o #{destination} #{source}")
17
+ end
18
+
19
+ def complete?
20
+ has_url_get? && existed?
21
+ end
22
+
23
+ def existed?
24
+ %i(check_file_is_file check_file_is_directory).any? do |command|
25
+ check_specific_command(command, destination)
26
+ end
27
+ end
28
+
29
+ def has_url_get?
30
+ check_command 'which curl'
31
+ end
32
+
33
+ def name
34
+ super || "url-get form #{source} to #{destination}"
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,47 @@
1
+ require 'slop'
2
+ require 'minarai/loaders/recipe_loader'
3
+ require 'minarai/errors/missing_recipe_path_error.rb'
4
+ require 'minarai/logger'
5
+
6
+ module Minarai
7
+ class Command
8
+ def initialize(args)
9
+ @args = args
10
+ end
11
+
12
+ def call
13
+ Minarai::Logger.info 'Minarai starting...'
14
+ abort_with_error_message unless recipe.valid?
15
+ recipe.runner.run
16
+ Minarai::Logger.info 'Minarai finish'
17
+ end
18
+
19
+ private
20
+
21
+ def abort_with_error_message
22
+ Minarai::Logger.error(recipe.errors) and abort
23
+ end
24
+
25
+ def recipe
26
+ @recipe ||= Minarai::Loaders::RecipeLoader.new(recipe_path, variable_path: variable_path).load
27
+ end
28
+
29
+ def recipe_path
30
+ slop_options.arguments[0] || (Minarai::Logger.error(recipe_missing_error) and abort)
31
+ end
32
+
33
+ def recipe_missing_error
34
+ Minarai::Errors::MissingRecipePathError.new
35
+ end
36
+
37
+ def variable_path
38
+ slop_options[:variables]
39
+ end
40
+
41
+ def slop_options
42
+ @slop_options ||= Slop.parse(@args, suppress_errors: true) do |option|
43
+ option.string '-v', '--variables', 'variable file for erb recipe file'
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,17 @@
1
+ require 'minarai/errors/base'
2
+
3
+ module Minarai
4
+ module Errors
5
+ class AttributeValidationError < Base
6
+ def initialize(attribute, error_message, name)
7
+ @attribute = attribute
8
+ @error_message = error_message
9
+ @name = name
10
+ end
11
+
12
+ def to_s
13
+ "`#{@attribute}` #{@error_message} @ #{@name}"
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,6 @@
1
+ module Minarai
2
+ module Errors
3
+ class Base < StandardError
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,15 @@
1
+ require 'minarai/errors/base'
2
+
3
+ module Minarai
4
+ module Errors
5
+ class InvalidActionTypeError < Base
6
+ def initialize(name)
7
+ @name = name
8
+ end
9
+
10
+ def to_s
11
+ "`type` is required @ #{@name}"
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ require 'minarai/errors/base'
2
+
3
+ module Minarai
4
+ module Errors
5
+ class MissingRecipePathError < Base
6
+ def to_s
7
+ 'file path of recipe is required'
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,75 @@
1
+ require 'yaml'
2
+ require 'pathname'
3
+ require 'erb'
4
+
5
+ module Minarai
6
+ module Loaders
7
+ class Base
8
+ def initialize(path)
9
+ @path = path
10
+ end
11
+
12
+ def load
13
+ case
14
+ when !existed_file?
15
+ raise "Does not exist file: #{pathname}"
16
+ when yml_file?
17
+ load_yaml_file
18
+ when erb_file?
19
+ load_erb_file
20
+ else
21
+ raise 'inalid extname error'
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def binding_for_erb
28
+ TOPLEVEL_BINDING
29
+ end
30
+
31
+ def loaded_class
32
+ raise NotImplementedError
33
+ end
34
+
35
+ def load_yaml_file
36
+ loaded_class.new(load_file_from_yaml)
37
+ end
38
+
39
+ def load_erb_file
40
+ self.class.new(parsed_erb_file.path).load
41
+ end
42
+
43
+ def parsed_erb
44
+ ERB.new(pathname.read).result(binding_for_erb)
45
+ end
46
+
47
+ def parsed_erb_file
48
+ @parsed_erb_file ||= Tempfile.open(['', '.yml']) do |tmp|
49
+ tmp.puts parsed_erb
50
+ tmp
51
+ end
52
+ end
53
+
54
+ def existed_file?
55
+ pathname.exist?
56
+ end
57
+
58
+ def yml_file?
59
+ %w(.yml yaml).include?(pathname.extname)
60
+ end
61
+
62
+ def erb_file?
63
+ pathname.extname == '.erb'
64
+ end
65
+
66
+ def load_file_from_yaml
67
+ YAML.load_file(pathname)
68
+ end
69
+
70
+ def pathname
71
+ @pathname ||= Pathname.new(@path)
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,39 @@
1
+ require 'minarai/recipe'
2
+ require 'minarai/loaders/base'
3
+ require 'minarai/loaders/variable_loader'
4
+ require 'minarai/variable'
5
+
6
+ module Minarai
7
+ module Loaders
8
+ class RecipeLoader < Base
9
+ def initialize(path, variable_path: nil)
10
+ super(path)
11
+ @variable_path = variable_path
12
+ end
13
+
14
+ private
15
+
16
+ def loaded_class
17
+ Minarai::Recipe
18
+ end
19
+
20
+ def has_variable_path?
21
+ !@variable_path.nil?
22
+ end
23
+
24
+ def binding_for_erb
25
+ variables.to_mash.binding
26
+ end
27
+
28
+ def variables
29
+ @variables ||= begin
30
+ if has_variable_path?
31
+ Minarai::Loaders::VariableLoader.new(@variable_path).load
32
+ else
33
+ Minarai::Variable.new({})
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end