configmonkey_cli 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +21 -0
  5. data/README.md +87 -0
  6. data/Rakefile +1 -0
  7. data/VERSION +1 -0
  8. data/bin/configmonkey +9 -0
  9. data/bin/configmonkey.sh +14 -0
  10. data/configmonkey_cli.gemspec +27 -0
  11. data/lib/configmonkey_cli.rb +43 -0
  12. data/lib/configmonkey_cli/application.rb +159 -0
  13. data/lib/configmonkey_cli/application/colorize.rb +22 -0
  14. data/lib/configmonkey_cli/application/configuration.rb +38 -0
  15. data/lib/configmonkey_cli/application/configuration.tpl +0 -0
  16. data/lib/configmonkey_cli/application/core.rb +78 -0
  17. data/lib/configmonkey_cli/application/dispatch.rb +81 -0
  18. data/lib/configmonkey_cli/application/manifest.rb +316 -0
  19. data/lib/configmonkey_cli/application/manifest_actions/base.rb +90 -0
  20. data/lib/configmonkey_cli/application/manifest_actions/chmod.rb +40 -0
  21. data/lib/configmonkey_cli/application/manifest_actions/copy.rb +38 -0
  22. data/lib/configmonkey_cli/application/manifest_actions/custom.rb +52 -0
  23. data/lib/configmonkey_cli/application/manifest_actions/inplace.rb +28 -0
  24. data/lib/configmonkey_cli/application/manifest_actions/invoke.rb +45 -0
  25. data/lib/configmonkey_cli/application/manifest_actions/link.rb +46 -0
  26. data/lib/configmonkey_cli/application/manifest_actions/mkdir.rb +41 -0
  27. data/lib/configmonkey_cli/application/manifest_actions/remove.rb +46 -0
  28. data/lib/configmonkey_cli/application/manifest_actions/rsync.rb +112 -0
  29. data/lib/configmonkey_cli/application/manifest_actions/rtfm.rb +32 -0
  30. data/lib/configmonkey_cli/application/manifest_actions/sync_links.rb +60 -0
  31. data/lib/configmonkey_cli/application/manifest_actions/template.rb +38 -0
  32. data/lib/configmonkey_cli/application/output_helper.rb +30 -0
  33. data/lib/configmonkey_cli/helper.rb +62 -0
  34. data/lib/configmonkey_cli/version.rb +4 -0
  35. metadata +162 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 1f88a813de764ee6b33978ab3acf57bd6b4d2c57e0e5352214f6044db20cd327
4
+ data.tar.gz: 1bcbb9340b2a616dbf22e6249ddfd6705f57ee95bc84ae0e70b7bfd421dedfb7
5
+ SHA512:
6
+ metadata.gz: 83f512210d85b8351587412ca44fe9abd4171aea9ae835ff225e238f1c1cd794ad9926962033d1745517256d121d2a629d7cb83f446c3448c426d38deeb6999e
7
+ data.tar.gz: ae82e4e9be85ef140e8dfa0993de9b786330a517ee6acc05e4b5138e4bb542ce654d4b213ac6e88e6b7c656921c067e9fb65f26591b7dab8b9dd60cbfd225575
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ lib/bundler/man
11
+ pkg
12
+ rdoc
13
+ spec/reports
14
+ test/tmp
15
+ test/version_tmp
16
+ tmp
17
+ dev
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in dle.gemspec
4
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2020, Sven Pachnit aka. 2called-chaos
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,87 @@
1
+ # Configmonkey CLI
2
+
3
+ Configmonkey is a very simple tool to "deploy" configurations on servers. Chef/Puppet for the brainless.
4
+
5
+ ---
6
+
7
+ ## Help
8
+ If you need help or have problems [open an issue](https://github.com/2called-chaos/configmonkey_cli/issues/new).
9
+
10
+
11
+ ## Features
12
+
13
+ * …
14
+
15
+
16
+ ## ToDo
17
+
18
+ * logging
19
+ * manifest generation
20
+ * [add something to the list](https://github.com/2called-chaos/configmonkey_cli/issues/new)
21
+
22
+
23
+ ## Requirements
24
+
25
+ * Ruby (>= 2.6)
26
+ * Unixoid OS (such as Ubuntu/Debian, OS X, maybe others), sorry Windows
27
+ * config files
28
+
29
+
30
+ ## Installation
31
+
32
+ * `gem install configmonkey_cli`
33
+ * Go into a folder with your configs (manage them in sub folders)
34
+ * ~~`configmonkey --generate-manifest`~~
35
+ * ~~Edit the created file manifest.rb to fit your needs~~
36
+ * Run `configmonkey -h`
37
+ * Check out the additional features below
38
+
39
+
40
+ ## Usage
41
+
42
+ To get a list of available options invoke Configmonkey with the `--help` or `-h` option:
43
+
44
+ Usage: configmonkey [options]
45
+ # Application options
46
+ --generate-manifest Generates an example manifest in current directory
47
+ -a, --accept accept all defaults
48
+ -b, --no-bell dont ring a bell when asked
49
+ -D, --diff change default diff tool
50
+ -f, --fake-host HOST override hostname
51
+ -i, --in DIR operate from this source directory instead of pwd
52
+ -o, --out DIR operate on this target directory instead of /
53
+ -l, --log [file] Log changes to file, defaults to ~/.configmonkey/logs/configmonkey.log
54
+ -M, --merge change default merge tool
55
+ -n, --dry-run Simulate changes only, does not perform destructive operations
56
+ -y, --yes accept all prompts with yes
57
+ --dev-dump-actions Dump actions and exit
58
+
59
+ # General options
60
+ -d, --debug [lvl=1] Enable debug output
61
+ -m, --monochrome Don't colorize output
62
+ -h, --help Shows this help
63
+ -v, --version Shows version and other info
64
+ -z Do not check for updates on GitHub (with -v/--version)
65
+
66
+ ## Application configuration
67
+
68
+
69
+
70
+
71
+ ## Contributing
72
+
73
+ Contributions are very welcome! Either report errors, bugs and propose features or directly submit code:
74
+
75
+ 1. Fork it
76
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
77
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
78
+ 4. Push to the branch (`git push origin my-new-feature`)
79
+ 5. Create new Pull Request
80
+
81
+ This might be helpful: `./bin/configmonkey.sh -nd 120 -i ./dev/gamesplanet-config -o ./dev/servers/www3 -f www3`
82
+
83
+
84
+ ## Legal
85
+
86
+ * © 2020, Sven Pachnit (www.bmonkeys.net)
87
+ * configmonkey_cli is licensed under the MIT license.
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ require "configmonkey_cli"
3
+ begin
4
+ Process.setproctitle("configmonkey_cli")
5
+ ConfigmonkeyCli::Application.dispatch(ENV, ARGV)
6
+ rescue Interrupt
7
+ puts("\nInterrupted")
8
+ exit 1
9
+ end
@@ -0,0 +1,14 @@
1
+ #!/bin/bash
2
+
3
+ # That's __FILE__ in BASH :)
4
+ # From: http://stackoverflow.com/questions/59895/can-a-bash-script-tell-what-directory-its-stored-in
5
+ SOURCE="${BASH_SOURCE[0]}"
6
+ while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
7
+ MCLDIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
8
+ SOURCE="$(readlink "$SOURCE")"
9
+ [[ $SOURCE != /* ]] && SOURCE="$MCLDIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
10
+ done
11
+ PROJECT_ROOT="$( cd -P "$( dirname "$SOURCE" )"/.. && pwd )"
12
+
13
+ # Actually run script
14
+ cd $PROJECT_ROOT && bundle exec ruby bin/configmonkey "$@"
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'configmonkey_cli/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "configmonkey_cli"
8
+ spec.version = ConfigmonkeyCli::VERSION
9
+ spec.authors = ["Sven Pachnit"]
10
+ spec.email = ["sven@bmonkeys.net"]
11
+ spec.summary = %q{Configmonkey CLI - dead simple helper for git based server configs}
12
+ spec.description = %q{Basically chef/puppet for the brainless}
13
+ spec.homepage = "https://github.com/2called-chaos/configmonkey_cli"
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 "activesupport"
22
+ spec.add_dependency "httparty"
23
+ spec.add_dependency "thor"
24
+ spec.add_development_dependency "pry"
25
+ spec.add_development_dependency "bundler"
26
+ spec.add_development_dependency "rake"
27
+ end
@@ -0,0 +1,43 @@
1
+ STDOUT.sync = true
2
+
3
+ # stdlib
4
+ require "benchmark"
5
+ require "fileutils"
6
+ require "optparse"
7
+ require "open3"
8
+ require "shellwords"
9
+ require "digest/sha1"
10
+
11
+ # 3rd party
12
+ require "active_support"
13
+ require "active_support/core_ext"
14
+ require "active_support/time_with_zone"
15
+ begin ; require "pry" ; rescue LoadError ; end
16
+ require "httparty"
17
+ require "thor"
18
+
19
+ # lib
20
+ require "configmonkey_cli/version"
21
+ require "configmonkey_cli/helper"
22
+ require "configmonkey_cli/application/core"
23
+ require "configmonkey_cli/application/output_helper"
24
+ require "configmonkey_cli/application/colorize"
25
+ require "configmonkey_cli/application/manifest"
26
+ require "configmonkey_cli/application/configuration"
27
+ require "configmonkey_cli/application/dispatch"
28
+ require "configmonkey_cli/application"
29
+
30
+ # actions
31
+ require "configmonkey_cli/application/manifest_actions/base"
32
+ require "configmonkey_cli/application/manifest_actions/chmod"
33
+ require "configmonkey_cli/application/manifest_actions/copy"
34
+ require "configmonkey_cli/application/manifest_actions/custom"
35
+ require "configmonkey_cli/application/manifest_actions/inplace"
36
+ require "configmonkey_cli/application/manifest_actions/invoke"
37
+ require "configmonkey_cli/application/manifest_actions/link"
38
+ require "configmonkey_cli/application/manifest_actions/mkdir"
39
+ require "configmonkey_cli/application/manifest_actions/rsync"
40
+ require "configmonkey_cli/application/manifest_actions/remove"
41
+ require "configmonkey_cli/application/manifest_actions/rtfm"
42
+ require "configmonkey_cli/application/manifest_actions/sync_links"
43
+ require "configmonkey_cli/application/manifest_actions/template"
@@ -0,0 +1,159 @@
1
+ module ConfigmonkeyCli
2
+ class Application
3
+ attr_reader :opts, :connections, :hooks, :env, :argv
4
+ include Helper
5
+ include OutputHelper
6
+ include Colorize
7
+ include Core
8
+ include Dispatch
9
+ include Configuration::AppHelper
10
+
11
+ # =========
12
+ # = Setup =
13
+ # =========
14
+ def self.dispatch *a
15
+ new(*a) do |app|
16
+ app.load_appconfig
17
+ app.parse_params
18
+ begin
19
+ app.dispatch
20
+ app.haltpoint
21
+ rescue Interrupt
22
+ app.abort("Interrupted", 1)
23
+ rescue SystemExit
24
+ app.abort("Aborted", 2)
25
+ ensure
26
+ app.fire(:cm_shutdown)
27
+ app.debug "#{Thread.list.length} threads remain..."
28
+ end
29
+ end
30
+ end
31
+
32
+ def initialize env, argv
33
+ @boot = Time.current
34
+ @env, @argv = env, argv
35
+ @hooks = {}
36
+ @connections = {}
37
+ @monitor = Monitor.new
38
+ @opts = {
39
+ working_directory: Dir.pwd, # -i flag
40
+ target_directory: "/", # -o flag
41
+ hostname: `hostname`.chomp, # -f flag
42
+ diff_tool: nil, # -D flag
43
+ merge_tool: nil, # -M flag
44
+ bell: true, # -b flag
45
+ default_accept: false, # -a flag
46
+ default_yes: false, # -y flag
47
+ dispatch: :index, # (internal) action to dispatch
48
+ simulation: false, # -n flag
49
+ check_for_updates: true, # -z flag
50
+ colorize: true, # -m flag
51
+ debug: false, # -d flag
52
+ # silent: false, # -s flag
53
+ # quiet: false, # -q flag
54
+ stdout: STDOUT, # (internal) STDOUT redirect
55
+ }
56
+ init_params
57
+ yield(self)
58
+ end
59
+
60
+ def find_diff_tool
61
+ [
62
+ opts[:diff_tool],
63
+ ENV["CM_DIFF"],
64
+ ENV["THOR_DIFF"],
65
+ ENV["RAILS_DIFF"],
66
+ "colordiff",
67
+ "git diff --no-index",
68
+ "vim -d",
69
+ "diff -u",
70
+ ].compact.each do |cmd|
71
+ if hit = `which #{cmd.split(" ").first}`.chomp.presence
72
+ debug "§diff-using:(#{hit})#{cmd}"
73
+ return cmd
74
+ else
75
+ debug "§diff-not-found:#{cmd}", 105
76
+ end
77
+ end
78
+ end
79
+
80
+ def find_merge_tool
81
+ [
82
+ opts[:merge_tool],
83
+ ENV["CM_MERGE"],
84
+ ENV["THOR_MERGE"],
85
+ (`git config merge.tool`.chomp rescue nil),
86
+ "vim -d",
87
+ "diff -u",
88
+ ].compact.each do |cmd|
89
+ if hit = `which #{cmd.split(" ").first}`.chomp.presence
90
+ debug "§merge-using:(#{hit})#{cmd}"
91
+ return cmd
92
+ else
93
+ debug "§merge-not-found:#{cmd}", 105
94
+ end
95
+ end
96
+ end
97
+
98
+ def to_s
99
+ "#<ConfigmonkeyCli::Application @boot=#{@boot} @opts=#{@opts} @running=#{@running}>"
100
+ end
101
+
102
+ def init_params
103
+ @optparse = OptionParser.new do |opts|
104
+ opts.banner = "Usage: configmonkey [options]"
105
+
106
+ opts.separator(c "# Application options", :blue)
107
+ opts.on("--generate-manifest", "Generates an example manifest in current directory") { @opts[:dispatch] = :generate_manifest }
108
+ opts.on("-a", "--accept", "accept all defaults") { @opts[:default_accept] = true }
109
+ opts.on("-b", "--no-bell", "dont ring a bell when asked") { @opts[:bell] = false }
110
+ opts.on("-D", "--diff", "change default diff tool") {|s| @opts[:diff_tool] = s }
111
+ opts.on("-f", "--fake-host HOST", "override hostname") {|s| @opts[:hostname] = s }
112
+ opts.on("-i", "--in DIR", "operate from this source directory instead of pwd") {|s| @opts[:working_directory] = s }
113
+ opts.on("-o", "--out DIR", "operate on this target directory instead of /") {|s| @opts[:target_directory] = s }
114
+ opts.on("-l", "--log [file]", "Log changes to file, defaults to ~/.configmonkey/logs/configmonkey.log") {|s| @opts[:logfile] = s || logger_filename }
115
+ opts.on("-M", "--merge", "change default merge tool") {|s| @opts[:merge_tool] = s }
116
+ opts.on("-n", "--dry-run", "Simulate changes only, does not perform destructive operations") { @opts[:simulation] = true }
117
+ opts.on("-y", "--yes", "accept all prompts with yes") { @opts[:default_yes] = true }
118
+ opts.on( "--dev-dump-actions", "Dump actions and exit") { @opts[:dev_dump_actions] = true }
119
+ # opts.on("-q", "--quiet", "Only print errors") { @opts[:quiet] = true }
120
+
121
+ opts.separator("\n" << c("# General options", :blue))
122
+ opts.on("-d", "--debug [lvl=1]", Integer, "Enable debug output") {|l| @opts[:debug] = l || 1 }
123
+ opts.on("-m", "--monochrome", "Don't colorize output") { @opts[:colorize] = false }
124
+ opts.on("-h", "--help", "Shows this help") { @opts[:dispatch] = :help }
125
+ opts.on("-v", "--version", "Shows version and other info") { @opts[:dispatch] = :info }
126
+ opts.on("-z", "Do not check for updates on GitHub (with -v/--version)") { @opts[:check_for_updates] = false }
127
+ end
128
+ end
129
+
130
+ def parse_params
131
+ @optparse.parse!(@argv)
132
+
133
+ # resolve diff/merge tool
134
+ @opts[:diff_tool] = find_diff_tool
135
+ @opts[:merge_tool] = find_merge_tool
136
+
137
+ # thor bell
138
+ ENV['THOR_ASK_BELL'] = "true" if @opts[:bell]
139
+
140
+ # thor no-colors
141
+ ENV['NO_COLOR'] = "true" if !@opts[:colorize]
142
+
143
+ # thor diff-tool
144
+ ENV['THOR_DIFF'] = opts[:diff_tool] if @opts[:diff_tool]
145
+ rescue OptionParser::ParseError => e
146
+ abort(e.message)
147
+ dispatch(:help)
148
+ exit 1
149
+ end
150
+
151
+ def sync &block
152
+ @monitor.synchronize(&block)
153
+ end
154
+
155
+ def running?
156
+ @running
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,22 @@
1
+ module ConfigmonkeyCli
2
+ class Application
3
+ module Colorize
4
+ COLORMAP = {
5
+ black: 30,
6
+ red: 31,
7
+ green: 32,
8
+ yellow: 33,
9
+ blue: 34,
10
+ magenta: 35,
11
+ cyan: 36,
12
+ white: 37,
13
+ }
14
+
15
+ def colorize str, color = :yellow
16
+ ccode = COLORMAP[color.to_sym] || raise(ArgumentError, "Unknown color #{color}!")
17
+ @opts[:colorize] ? "\e[#{ccode}m#{str}\e[0m" : "#{str}"
18
+ end
19
+ alias_method :c, :colorize
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,38 @@
1
+ module ConfigmonkeyCli
2
+ class Application
3
+ class Configuration
4
+ module AppHelper
5
+ def cm_cfg_path
6
+ ENV["CM_CFGDIR"].presence || File.expand_path("~/.configmonkey")
7
+ end
8
+
9
+ def cm_cfg_configfile
10
+ "#{cm_cfg_path}/config.rb"
11
+ end
12
+
13
+ def load_appconfig
14
+ return unless File.exist?(cm_cfg_configfile)
15
+ eval File.read(cm_cfg_configfile, encoding: "utf-8"), binding, cm_cfg_configfile
16
+ end
17
+
18
+ def generate_manifest directory
19
+ #FileUtils.mkdir_p(config_directory)
20
+ #File.open(config_filename(name), "w", encoding: "utf-8") do |f|
21
+ # f << File.read("#{File.dirname(__FILE__)}/configuration.tpl", encoding: "utf-8")
22
+ #end
23
+ end
24
+
25
+ def load_and_execute_manifest
26
+ manifest = Manifest.new(self, File.realpath(File.expand_path(opts[:working_directory])), @argv[0])
27
+ if opts[:dev_dump_actions]
28
+ manifest._dump!
29
+ elsif opts[:simulation]
30
+ manifest._simulate!
31
+ else
32
+ manifest._execute!
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end