gene_system 0.3.2

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.
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