gene_system 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile ADDED
@@ -0,0 +1,19 @@
1
+ require 'private_gem/tasks'
2
+ require 'bundler/gem_tasks'
3
+ require 'bump/tasks'
4
+ require 'rspec/core/rake_task'
5
+ require 'rubocop/rake_task'
6
+ require 'rubycritic/rake_task'
7
+ require 'yard'
8
+
9
+ RSpec::Core::RakeTask.new(:spec)
10
+ RuboCop::RakeTask.new
11
+
12
+ RubyCritic::RakeTask.new do |task|
13
+ task.paths = FileList['lib/**/*.rb'] - FileList['spec/**/*_spec.rb']
14
+ task.options = '--no-browser --path ./target/reports/critique'
15
+ end
16
+
17
+ YARD::Rake::YardocTask.new
18
+
19
+ task default: %i[spec rubocop rubycritic yard]
data/bin/genesystem ADDED
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift(__dir__ + '/../lib')
4
+
5
+ require 'rubygems'
6
+ require 'optparse'
7
+ require 'highline'
8
+
9
+ require 'gene_system'
10
+ require 'gene_system/cli'
11
+
12
+ USAGE = "GeneSystem system configuration tool
13
+
14
+ Usage:\tgenesystem <command> <variables> <opts>
15
+ Options:
16
+ \s\s\s\s--trace\t\t trace mode on
17
+ -h, --help\t\t print usage
18
+
19
+ Commands:
20
+ new <rel>\t\t creates a new manifest
21
+ install <rel>\t\t applies install steps specified in manifest
22
+ remove <rel>\t\t applies remove steps specified in manifest
23
+ ".freeze
24
+
25
+ @trace = false
26
+ @overwrite = false
27
+
28
+ OptionParser.new do |opts|
29
+ opts.banner = USAGE
30
+ opts.on('--trace') { @trace = true }
31
+
32
+ opts.on_tail('-h', '--help') do
33
+ GeneSystem::CLI.print_message_and_exit(USAGE)
34
+ end
35
+ end.parse!
36
+
37
+ begin
38
+ raise 'ERROR: no command provided' unless ARGV[0]
39
+
40
+ cmd = ARGV.shift
41
+ GeneSystem::CLI::Commands.public_send(
42
+ cmd.to_sym,
43
+ ARGV
44
+ )
45
+ rescue StandardError => e
46
+ GeneSystem::CLI.print_message(e)
47
+ GeneSystem::CLI.print_message(e.backtrace) if @trace
48
+ GeneSystem::CLI.print_message("\n")
49
+ GeneSystem::CLI.print_message_and_exit(USAGE)
50
+ end
51
+
52
+ exit(0)
@@ -0,0 +1,87 @@
1
+ local conf = {
2
+ variables: {
3
+ apps: [
4
+ {
5
+ "name": "virtualbox",
6
+ "version": "6.0.1",
7
+ },
8
+ {
9
+ "name": "vagrant",
10
+ "version": "9.0.2",
11
+ },
12
+ ],
13
+
14
+ bins: [
15
+ "libc",
16
+ "libd",
17
+ "libe"
18
+ ]
19
+ }
20
+ };
21
+
22
+ {
23
+ "name": "macos_ruby_dev",
24
+ "version": "0.1.1",
25
+ "platform": "macos",
26
+ "metadata": {
27
+ "gene_system": {
28
+ "version": "0.1.0"
29
+ },
30
+ },
31
+ "steps": [
32
+ // install apps
33
+ {
34
+ "name": "install " + app.name,
35
+ "exe": {
36
+ "install": {
37
+ "skip": "which yolo",
38
+ "cmd": [
39
+ "echo install " + app.name + app.version
40
+ ],
41
+ },
42
+ "remove": {
43
+ "cmd": [
44
+ "echo remove " + app.name + app.version
45
+ ],
46
+ },
47
+ },
48
+ "tags": "app " + app.name
49
+ } for app in conf.variables.apps
50
+ ] + [
51
+ // install bins
52
+ {
53
+ "name": "install " + bin,
54
+ "exe": {
55
+ "install": {
56
+ "cmd": [
57
+ "echo install " + bin
58
+ ],
59
+ },
60
+ "remove": {
61
+ "cmd": [
62
+ "echo remove " + bin
63
+ ],
64
+ },
65
+ },
66
+ "tags": "app " + bin
67
+ } for bin in conf.variables.bins
68
+ ] + [
69
+ {
70
+ "name": "ask for input",
71
+ "exe": {
72
+ "install": {
73
+ "prompts": [
74
+ {
75
+ "prompt": "Please enter your name",
76
+ "var": "name",
77
+ },
78
+ ],
79
+ "cmd": [
80
+ "echo 'Hello {{name}}'"
81
+ ],
82
+ },
83
+ },
84
+ "tags": "input"
85
+ },
86
+ ],
87
+ }
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'gene_system/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'gene_system'
9
+ spec.version = GeneSystem::VERSION
10
+ spec.authors = ['Andrew Bigger']
11
+ spec.email = ['andrew.bigger@gmail.com']
12
+ spec.summary = 'System configuration tool for applying personal settings to a new machine.'
13
+ spec.homepage = 'https://github.com/andrewbigger/gene_system'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_dependency 'hashie'
22
+ spec.add_dependency 'highline', '~> 2.0'
23
+ spec.add_dependency 'jsonnet'
24
+ spec.add_dependency 'logger', '~> 1.4'
25
+ spec.add_dependency 'os'
26
+ spec.add_dependency 'ruby-handlebars', '~> 0.4'
27
+
28
+ spec.add_development_dependency 'bump', '~> 0.6'
29
+ spec.add_development_dependency 'byebug', '~> 11.0'
30
+ spec.add_development_dependency 'doxie'
31
+ spec.add_development_dependency 'private_gem', '~> 1.1'
32
+ spec.add_development_dependency 'pry', '~> 0.11'
33
+ spec.add_development_dependency 'puma', '~> 4.3'
34
+ spec.add_development_dependency 'rake', '~> 13.0'
35
+ spec.add_development_dependency 'rspec', '~> 3.7', '>= 3.7.0'
36
+ spec.add_development_dependency 'rubocop', '~> 0.58'
37
+ spec.add_development_dependency 'rubycritic', '~> 3.4', '>= 3.4.0'
38
+ spec.add_development_dependency 'simplecov', '~> 0.16'
39
+ spec.add_development_dependency 'yard', '~> 0.9'
40
+ end
@@ -0,0 +1,9 @@
1
+ require 'gene_system/version'
2
+ require 'gene_system/generators'
3
+ require 'gene_system/manifest'
4
+ require 'gene_system/step'
5
+ require 'gene_system/platform'
6
+
7
+ # GeneSystem is the namespace for gene_system
8
+ module GeneSystem
9
+ end
@@ -0,0 +1,76 @@
1
+ require 'gene_system/cli/commands'
2
+
3
+ require 'hashie'
4
+
5
+ module GeneSystem
6
+ # Command line interface helpers and actions
7
+ module CLI
8
+ # CLI Helpers
9
+ class <<self
10
+ ##
11
+ # Creates logger for printing messages
12
+ #
13
+ # Sets the formatter to output only the provided message to the
14
+ # specified IO
15
+ #
16
+ # @param [IO] out - default: STDOUT
17
+ #
18
+ # @return [Logger]
19
+ #
20
+ def logger(out = STDOUT)
21
+ @logger ||= Logger.new(out)
22
+ @logger.formatter = proc do |_sev, _time, _prog, msg|
23
+ "#{msg}\n"
24
+ end
25
+
26
+ @logger
27
+ end
28
+
29
+ ##
30
+ # Prints command line message to STDOUT
31
+ #
32
+ # For use when printing info messages for a user to STDOUT
33
+ #
34
+ # @param [String] message - message to be printed
35
+ #
36
+ def print_message(message)
37
+ logger.info(message)
38
+ end
39
+
40
+ ##
41
+ # Prints warning to STDOUT
42
+ #
43
+ # For use when printing warn messages to STDOUT
44
+ #
45
+ # @param [String] message - message to be printed
46
+ #
47
+ def print_warning(message)
48
+ logger.warn(message)
49
+ end
50
+
51
+ ##
52
+ # Prints error to STDERR
53
+ #
54
+ # For indicating fatal message to user
55
+ #
56
+ # @param [String] message - message to be printed
57
+ #
58
+ def print_error(message)
59
+ logger(STDERR).error(message)
60
+ end
61
+
62
+ ##
63
+ # Prints a message and then exits with given status code
64
+ #
65
+ # This will terminate the program with the given status code
66
+ #
67
+ # @param [String] message - message to be printed
68
+ # @param [Integer] exit_code - exit status (default: 1)
69
+ #
70
+ def print_message_and_exit(message, exit_code = 1)
71
+ print_message(message)
72
+ exit(exit_code)
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,109 @@
1
+ require 'highline'
2
+
3
+ module GeneSystem
4
+ module CLI
5
+ # CLI Actions
6
+ module Commands
7
+ class <<self
8
+ ##
9
+ # Creates a new, blank manifest with at the specified
10
+ # destination with the given name
11
+ #
12
+ # It is expected that the first argument provided to the
13
+ # command will be the name of the manifest. If this is not
14
+ # provided then a RuntimeError will be raised.
15
+ #
16
+ # @param dest [String]
17
+ # @param args [Array]
18
+ #
19
+ def new(args = [])
20
+ manifest_name = args.shift
21
+
22
+ raise 'no manifest name provided' unless manifest_name
23
+
24
+ GeneSystem::Generators.render_empty_manifest(
25
+ manifest_name,
26
+ Dir.pwd
27
+ )
28
+ end
29
+
30
+ ##
31
+ # Applies install instructions from a manifest to the host system
32
+ #
33
+ # @param args [Array]
34
+ #
35
+ def install(args = [])
36
+ manifest = load_manifest(args)
37
+ platform = GeneSystem::Platform.new
38
+
39
+ manifest.steps.each do |step|
40
+ next if skip?(step, platform)
41
+
42
+ vars = ask(step.install.prompts)
43
+ platform.execute_commands(step.install.cmd, vars)
44
+ end
45
+
46
+ GeneSystem::CLI.print_message("\nmanifest successfully installed")
47
+ end
48
+
49
+ ##
50
+ # Asks for user input when given prompts
51
+ #
52
+ # @param prompts [Array]
53
+ #
54
+ # @return Hashie::Mash
55
+ #
56
+ def ask(prompts = [])
57
+ answers = Hashie::Mash.new
58
+ return answers if prompts.nil?
59
+
60
+ cli = HighLine.new
61
+
62
+ prompts.each do |prompt|
63
+ resp = cli.ask(prompt.prompt)
64
+ answers[prompt.var] = resp
65
+ end
66
+
67
+ answers
68
+ end
69
+
70
+ ##
71
+ # Applies remove instructions from a manifest to the host system
72
+ #
73
+ # @param args [Array]
74
+ #
75
+ def remove(args = [])
76
+ manifest = load_manifest(args)
77
+ platform = GeneSystem::Platform.new
78
+
79
+ manifest.steps.each do |step|
80
+ platform.execute_commands(step.remove.cmd)
81
+ end
82
+
83
+ GeneSystem::CLI.print_message("\nmanifest successfully removed")
84
+ end
85
+
86
+ private
87
+
88
+ def load_manifest(args)
89
+ manifest_rel = args.shift
90
+ raise 'no manifest path provided' unless manifest_rel
91
+
92
+ manifest_path = File.join(Dir.pwd, manifest_rel)
93
+
94
+ unless File.exist?(manifest_path)
95
+ raise "cannot find manifest at #{manifest_path}"
96
+ end
97
+
98
+ GeneSystem::Manifest.new_from_file(manifest_path)
99
+ end
100
+
101
+ def skip?(step, platform)
102
+ return false if step.install.skip.nil?
103
+
104
+ platform.execute_command(step.install.skip).zero?
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,58 @@
1
+ require 'json'
2
+
3
+ module GeneSystem
4
+ # Generators create empty projects for the gene_system gem
5
+ module Generators
6
+ # Default sample step
7
+ DEFAULT_STEP = {
8
+ 'name' => 'say hello',
9
+ 'exe' => {
10
+ 'install' => {
11
+ 'cmd' => [
12
+ 'echo hello'
13
+ ]
14
+ },
15
+ 'remove' => {
16
+ 'cmd' => [
17
+ 'echo goodbye'
18
+ ]
19
+ }
20
+ },
21
+ 'tags' => 'example step'
22
+ }.freeze
23
+
24
+ # Function that creates a named, empty manifest
25
+ TEMPLATE_MANIFEST = lambda do |name|
26
+ {
27
+ 'name' => name,
28
+ 'version' => '0.0.1',
29
+ 'metadata' => {
30
+ 'gene_system' => {
31
+ 'version' => GeneSystem::VERSION
32
+ }
33
+ },
34
+ 'steps' => [
35
+ DEFAULT_STEP
36
+ ]
37
+ }
38
+ end
39
+
40
+ class <<self
41
+ ##
42
+ # Renders empty manifest at specified path
43
+ #
44
+ # @param [String] name
45
+ # @param [String] path
46
+ #
47
+ def render_empty_manifest(name, path)
48
+ manifest_path = File.join(path, "#{name}.json")
49
+
50
+ File.open(manifest_path, 'w') do |f|
51
+ f.write(
52
+ TEMPLATE_MANIFEST.call(name).to_json
53
+ )
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end