ConfigLMM 0.1.0

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 (104) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.yardopts +4 -0
  4. data/CHANGELOG.md +5 -0
  5. data/Examples/Android.mm.yaml +8 -0
  6. data/Examples/Apps/Blog.mm.yaml +7 -0
  7. data/Examples/Apps/Jellyfin.mm.yaml +3 -0
  8. data/Examples/Implemented.mm.yaml +155 -0
  9. data/Examples/Keys.ini +7 -0
  10. data/Examples/Linux.mm.yaml +16 -0
  11. data/Examples/Windows.mm.yaml +11 -0
  12. data/Examples/configlmmAuth.sh +26 -0
  13. data/Plugins/Apps/ArchiSteamFarm/ArchiSteamFarm.conf.erb +38 -0
  14. data/Plugins/Apps/ArchiSteamFarm/ArchiSteamFarm.lmm.rb +19 -0
  15. data/Plugins/Apps/IPFS/IPFS.conf.erb +44 -0
  16. data/Plugins/Apps/IPFS/IPFS.lmm.rb +23 -0
  17. data/Plugins/Apps/InfluxDB/InfluxDB.conf.erb +34 -0
  18. data/Plugins/Apps/InfluxDB/InfluxDB.lmm.rb +19 -0
  19. data/Plugins/Apps/Jackett/Jackett.conf.erb +38 -0
  20. data/Plugins/Apps/Jackett/Jackett.lmm.rb +19 -0
  21. data/Plugins/Apps/Jellyfin/Jellyfin.conf.erb +59 -0
  22. data/Plugins/Apps/Jellyfin/Jellyfin.lmm.rb +23 -0
  23. data/Plugins/Apps/Mastodon/Mastodon.conf.erb +81 -0
  24. data/Plugins/Apps/Mastodon/Mastodon.lmm.rb +23 -0
  25. data/Plugins/Apps/Matrix/Matrix.conf.erb +36 -0
  26. data/Plugins/Apps/Matrix/Matrix.lmm.rb +23 -0
  27. data/Plugins/Apps/Netdata/Netdata.conf.erb +37 -0
  28. data/Plugins/Apps/Netdata/Netdata.lmm.rb +23 -0
  29. data/Plugins/Apps/Nextcloud/Nextcloud.conf.erb +165 -0
  30. data/Plugins/Apps/Nextcloud/Nextcloud.lmm.rb +23 -0
  31. data/Plugins/Apps/Nginx/config-lmm/errors.conf +31 -0
  32. data/Plugins/Apps/Nginx/config-lmm/private.conf +6 -0
  33. data/Plugins/Apps/Nginx/config-lmm/proxy.conf +15 -0
  34. data/Plugins/Apps/Nginx/config-lmm/public.conf +3 -0
  35. data/Plugins/Apps/Nginx/config-lmm/ssl.conf +18 -0
  36. data/Plugins/Apps/Nginx/main.conf +30 -0
  37. data/Plugins/Apps/Nginx/nginx.conf +90 -0
  38. data/Plugins/Apps/Nginx/nginx.lmm.rb +62 -0
  39. data/Plugins/Apps/Nginx/proxy.conf.erb +31 -0
  40. data/Plugins/Apps/Odoo/Odoo.conf.erb +44 -0
  41. data/Plugins/Apps/Odoo/Odoo.lmm.rb +23 -0
  42. data/Plugins/Apps/Pterodactyl/Pterodactyl.conf.erb +50 -0
  43. data/Plugins/Apps/Pterodactyl/Pterodactyl.lmm.rb +30 -0
  44. data/Plugins/Apps/Pterodactyl/Wings.conf.erb +38 -0
  45. data/Plugins/Apps/Sunshine/Sunshine.conf.erb +31 -0
  46. data/Plugins/Apps/Sunshine/Sunshine.lmm.rb +21 -0
  47. data/Plugins/Apps/Vaultwarden/Vaultwarden.conf.erb +48 -0
  48. data/Plugins/Apps/Vaultwarden/Vaultwarden.lmm.rb +25 -0
  49. data/Plugins/Apps/bitmagnet/bitmagnet.conf.erb +35 -0
  50. data/Plugins/Apps/bitmagnet/bitmagnet.lmm.rb +19 -0
  51. data/Plugins/Apps/gollum/config.ru +11 -0
  52. data/Plugins/Apps/gollum/gollum.conf.erb +41 -0
  53. data/Plugins/Apps/gollum/gollum.lmm.rb +52 -0
  54. data/Plugins/OS/Linux.lmm.rb +64 -0
  55. data/Plugins/OS/Routers/Aruba/ArubaInstant.lmm.rb +144 -0
  56. data/Plugins/Platforms/GitHub.lmm.rb +57 -0
  57. data/Plugins/Platforms/GoDaddy/GoDaddy.lmm.rb +83 -0
  58. data/Plugins/Platforms/GoDaddy/zone.txt.erb +13 -0
  59. data/Plugins/Platforms/porkbun.lmm.rb +129 -0
  60. data/Plugins/Platforms/porkbun_spec.rb +110 -0
  61. data/Plugins/Services/DNS/AmberBit.lmm.rb +14 -0
  62. data/Plugins/Services/DNS/ArubaItDNS.lmm.rb +14 -0
  63. data/Plugins/Services/DNS/NICLV.lmm.rb +18 -0
  64. data/Plugins/Services/DNS/PowerDNS.lmm.rb +261 -0
  65. data/Plugins/Services/DNS/tonic.lmm.rb +126 -0
  66. data/README.md +337 -0
  67. data/Rakefile +15 -0
  68. data/UNLICENSE +24 -0
  69. data/bin/configlmm +7 -0
  70. data/bin/console +11 -0
  71. data/bin/setup +8 -0
  72. data/lib/ConfigLMM/Framework/plugins/dns.rb +63 -0
  73. data/lib/ConfigLMM/Framework/plugins/errors.rb +23 -0
  74. data/lib/ConfigLMM/Framework/plugins/nginxApp.rb +55 -0
  75. data/lib/ConfigLMM/Framework/plugins/plugin.rb +167 -0
  76. data/lib/ConfigLMM/Framework/plugins/ssh.rb +37 -0
  77. data/lib/ConfigLMM/Framework/plugins/store.rb +57 -0
  78. data/lib/ConfigLMM/Framework/plugins.rb +5 -0
  79. data/lib/ConfigLMM/Framework/registrator.rb +32 -0
  80. data/lib/ConfigLMM/Framework.rb +9 -0
  81. data/lib/ConfigLMM/LMM/plugins.rb +5 -0
  82. data/lib/ConfigLMM/LMM.rb +8 -0
  83. data/lib/ConfigLMM/cli.rb +161 -0
  84. data/lib/ConfigLMM/command.rb +53 -0
  85. data/lib/ConfigLMM/commands/build.rb +41 -0
  86. data/lib/ConfigLMM/commands/cleanup.rb +30 -0
  87. data/lib/ConfigLMM/commands/configsCommand.rb +167 -0
  88. data/lib/ConfigLMM/commands/deploy.rb +39 -0
  89. data/lib/ConfigLMM/commands/diff.rb +45 -0
  90. data/lib/ConfigLMM/commands/list.rb +15 -0
  91. data/lib/ConfigLMM/commands/refresh.rb +46 -0
  92. data/lib/ConfigLMM/commands/types.rb +35 -0
  93. data/lib/ConfigLMM/commands/validate.rb +49 -0
  94. data/lib/ConfigLMM/context.rb +52 -0
  95. data/lib/ConfigLMM/io/configList.rb +98 -0
  96. data/lib/ConfigLMM/io/path.rb +48 -0
  97. data/lib/ConfigLMM/io/source.rb +47 -0
  98. data/lib/ConfigLMM/io.rb +2 -0
  99. data/lib/ConfigLMM/state.rb +78 -0
  100. data/lib/ConfigLMM/utils/filters.rb +126 -0
  101. data/lib/ConfigLMM/version.rb +5 -0
  102. data/lib/ConfigLMM.rb +6 -0
  103. data/sig/ConfigLMM.rbs +4 -0
  104. metadata +485 -0
@@ -0,0 +1,167 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'errors'
4
+ require_relative 'store'
5
+ require 'http'
6
+ require 'fileutils'
7
+
8
+ module ConfigLMM
9
+ module Framework
10
+
11
+ class Plugin
12
+
13
+
14
+ def self.inherited(plugin)
15
+ Store.registerPlugin(plugin)
16
+ end
17
+
18
+ def self.id
19
+ @ID ||= self.normalizeId(self.className.to_s)
20
+ end
21
+
22
+ def self.addMeta(*fields)
23
+ fields.each do |field|
24
+ self.define_singleton_method(field) do |value|
25
+ @Meta ||= {}
26
+ @Meta[field] = value
27
+ end
28
+ end
29
+ end
30
+
31
+ def self.persistBuildDir
32
+ @PersistBuildDir = true
33
+ end
34
+
35
+ def self.persistBuildDir?
36
+ @PersistBuildDir == true
37
+ end
38
+
39
+ class << self
40
+ alias :className :name
41
+ end
42
+
43
+ addMeta :name, :description
44
+
45
+ def initialize(logger, prompt, plugins)
46
+ @Logger = logger
47
+ @Prompt = prompt
48
+ @Plugins = plugins
49
+ @Diff = {}
50
+ end
51
+
52
+ def id
53
+ self.class.id
54
+ end
55
+
56
+ def self.actionMethod(type, action)
57
+ name = type.to_s
58
+ name[0] = name[0].upcase
59
+ ('action' + name + action.to_s.capitalize).to_sym
60
+ end
61
+
62
+ def hasAction?(type, action)
63
+ self.methods.include?(self.class.actionMethod(type, action))
64
+ end
65
+
66
+ def diff
67
+ @Diff
68
+ end
69
+
70
+ def cleanup(configs, state, context, options)
71
+ # Do nothing
72
+ end
73
+
74
+ protected
75
+
76
+ def logger
77
+ @Logger
78
+ end
79
+
80
+ def prompt
81
+ @Prompt
82
+ end
83
+
84
+ def plugins
85
+ @Plugins
86
+ end
87
+
88
+ def shouldMatch(id, targetKey, stateKey, target, activeState)
89
+ if target[targetKey] != activeState[stateKey]
90
+ @Diff.update({targetKey => [target[targetKey], activeState[stateKey]]})
91
+ end
92
+ end
93
+
94
+ def fileWrite(target, data, dry)
95
+ if dry
96
+ prompt.say('Would write file ' + target)
97
+ else
98
+ File.write(target, data)
99
+ end
100
+ end
101
+
102
+ def copy(source, target, dry)
103
+ if dry
104
+ prompt.say('Would copy ' + source + ' to ' + target)
105
+ else
106
+ FileUtils.cp_r(source, target, noop: dry)
107
+ end
108
+ end
109
+
110
+ def copyNotPresent(source, target, dry)
111
+ if !File.exist?(target + File.basename(source))
112
+ if dry
113
+ prompt.say('Would copy ' + source + ' to ' + target)
114
+ else
115
+ FileUtils.cp_r(source, target, noop: dry)
116
+ end
117
+ end
118
+ end
119
+
120
+ def rm(path, dry)
121
+ if dry
122
+ prompt.say('Would remove ' + path)
123
+ else
124
+ FileUtils.rm_r(path, noop: dry)
125
+ end
126
+ end
127
+
128
+ def mkdir(target, dry)
129
+ if dry
130
+ prompt.say('Would create ' + target)
131
+ else
132
+ FileUtils.mkdir_p(target)
133
+ end
134
+ end
135
+
136
+ def chown(user, group, target, dry)
137
+ if dry
138
+ prompt.say("Would chown #{target} as #{user}:#{group}")
139
+ else
140
+ FileUtils.chown_R(user, group, target)
141
+ end
142
+ end
143
+
144
+ def renderTemplate(template, target, outputPath, options)
145
+ variables = {
146
+ config: target,
147
+ }
148
+ result = template.result_with_hash(variables)
149
+ mkdir(File.dirname(outputPath), options['dry'])
150
+ if options['dry']
151
+ prompt.say('Would write to ' + outputPath)
152
+ else
153
+ File.write(outputPath, result)
154
+ end
155
+ end
156
+
157
+ def self.normalizeId(id)
158
+ id = id.split('::').last
159
+ if id.downcase.end_with?('plugin')
160
+ id = id[0...-6]
161
+ end
162
+ id.to_sym
163
+ end
164
+
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,37 @@
1
+
2
+ # frozen_string_literal: true
3
+
4
+ require_relative 'plugin'
5
+ require_relative 'errors'
6
+ require 'net/ssh'
7
+
8
+ module ConfigLMM
9
+ module Framework
10
+
11
+ class SSH < Framework::Plugin
12
+
13
+ def parseLocation(location)
14
+ user, hostname = location.split('@')
15
+ if hostname.nil?
16
+ hostname = user
17
+ user = nil
18
+ end
19
+ hostname, port = hostname.split(':')
20
+ port = 22 unless port
21
+ {
22
+ hostname: hostname,
23
+ user: user,
24
+ port: port
25
+ }
26
+ end
27
+
28
+ def checkSSHAuth!(location, password)
29
+ creds = parseLocation(location)
30
+ Net::SSH.start(creds[:hostname], creds[:user], password: password, port: creds[:port]) do |ssh|
31
+ # All good if we got here
32
+ end
33
+ end
34
+
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'errors'
4
+
5
+ module ConfigLMM
6
+ module Framework
7
+ class Store
8
+
9
+ @@AvailablePlugins = {}
10
+
11
+ def self.registerPlugin(plugin)
12
+ @@AvailablePlugins[plugin.id] = plugin
13
+ end
14
+
15
+ def self.plugins
16
+ @@AvailablePlugins.values
17
+ end
18
+
19
+ def self.countPlugins
20
+ @@AvailablePlugins.length
21
+ end
22
+
23
+ def self.plugin(pluginId)
24
+ raise PluginMissingError.new("Couldn't find plugin '#{pluginId}'") unless @@AvailablePlugins.key?(pluginId)
25
+ @@AvailablePlugins[pluginId]
26
+ end
27
+
28
+ def self.leafPlugins
29
+ nonLeaves = Set.new
30
+ @@AvailablePlugins.each do |id, plugin|
31
+ plugin.ancestors.each do |ancestor|
32
+ nonLeaves << ancestor if ancestor != plugin
33
+ end
34
+ end
35
+ @@AvailablePlugins.reject do |id, plugin|
36
+ nonLeaves.include?(plugin)
37
+ end
38
+ end
39
+
40
+ def self.boot(logger, prompt, plugins)
41
+ leafPlugins.each do |id, plugin|
42
+ self.initPlugin(id, logger, prompt, plugins)
43
+ rescue PluginLoadError => error
44
+ logger.warn("Plugin '#{id}' failed to load!\n#{error.message}" + (error.cause ? ' - ' : ''), error.cause)
45
+ end
46
+ true
47
+ end
48
+
49
+ def self.initPlugin(pluginId, logger, prompt, plugins)
50
+ pluginId = pluginId.to_sym
51
+ raise 'Recursive/cyclic plugin' if plugins.key?(pluginId)
52
+ plugins[pluginId] = @@AvailablePlugins[pluginId].new(logger, prompt, plugins)
53
+ end
54
+
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'plugins/dns'
4
+ require_relative 'plugins/nginxApp'
5
+ require_relative 'plugins/ssh'
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConfigLMM
4
+ module Framework
5
+ module Registrator
6
+
7
+ @BasePaths = []
8
+
9
+ def self.addPath(basePath)
10
+ @BasePaths << basePath
11
+ end
12
+
13
+ def self.registerAll(logger)
14
+ @BasePaths.each do |basePath|
15
+ self.register(basePath, logger)
16
+ end
17
+ end
18
+
19
+ protected
20
+
21
+ def self.register(basePath, logger)
22
+ Dir.glob(basePath + 'Plugins/**/**.lmm.rb').each do |file|
23
+ require file
24
+ rescue ScriptError => error
25
+ logger.error("Failed to load #{File.realdirpath(file)}\n", error)
26
+ raise error
27
+ end
28
+ end
29
+
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConfigLMM
4
+ module Framework
5
+ end
6
+ end
7
+
8
+ require_relative 'Framework/registrator'
9
+ require_relative 'Framework/plugins'
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../Framework/registrator'
4
+
5
+ ConfigLMM::Framework::Registrator.addPath(__dir__ + '/../../../')
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConfigLMM
4
+ module LMM
5
+ end
6
+ end
7
+
8
+ require_relative 'LMM/plugins'
@@ -0,0 +1,161 @@
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
3
+
4
+ require 'thor'
5
+ require_relative 'LMM'
6
+
7
+ module ConfigLMM
8
+ # Handle the application command line parsing
9
+ # and the dispatch to various command objects
10
+ #
11
+ # @api public
12
+ class CLI < Thor
13
+ ArgumentError = Class.new(RuntimeError)
14
+ MissingArgument = Class.new(ArgumentError)
15
+ InvalidOption = Class.new(ArgumentError)
16
+
17
+ #class_option :locations, type: :string, default: '', group: :configs, desc: 'Filter by config file locations'
18
+ #class_option :things, type: :string, default: '', group: :configs, desc: 'Filter things to use'
19
+ class_option :level, type: :string, enum: ['debug', 'info', 'warn', 'error'], default: 'info', desc: 'Logging level to use'
20
+ class_option :dry, aliases: '-n', type: :boolean, desc: 'Only show actions without performing'
21
+
22
+ desc 'version', 'Show program\'s version'
23
+ def version
24
+ require_relative 'version'
25
+ puts "v" + ConfigLMM::VERSION
26
+ end
27
+ map %w[--version -v] => :version
28
+
29
+
30
+ desc 'list [CONFIGS...]', 'List things'
31
+ method_option :help, aliases: '-h', type: :boolean,
32
+ desc: 'Display usage information'
33
+ def list(*configPaths)
34
+ handleCommand(:list, configPaths, options)
35
+ end
36
+
37
+
38
+ desc 'validate [CONFIGS...]', 'Check whether the configuration is valid'
39
+ method_option :help, aliases: '-h', type: :boolean,
40
+ desc: 'Display usage information'
41
+ def validate(*configPaths)
42
+ handleCommand(:validate, configPaths, options)
43
+ end
44
+
45
+ desc 'refresh [CONFIGS...]', 'Update local state to match deployed things'
46
+ method_option :help, aliases: '-h', type: :boolean,
47
+ desc: 'Display usage information'
48
+ method_option :state, aliases: '-s', type: :string,
49
+ desc: 'Path to the state file'
50
+ method_option :context, aliases: '-c', type: :string,
51
+ desc: 'Path to context file'
52
+ def refresh(*configPaths)
53
+ handleCommand(:refresh, configPaths, options)
54
+ end
55
+
56
+
57
+ desc 'diff [CONFIGS...]', 'Show changes that will be applied with next deploy'
58
+ method_option :help, aliases: '-h', type: :boolean,
59
+ desc: 'Display usage information'
60
+ method_option :state, aliases: '-s', type: :string,
61
+ desc: 'Path to the state file'
62
+ method_option :context, aliases: '-c', type: :string,
63
+ desc: 'Path to context file'
64
+ def diff(*configPaths)
65
+ handleCommand(:diff, configPaths, options)
66
+ end
67
+
68
+
69
+ desc 'build [CONFIGS...]', 'Build configuration in deployable form'
70
+ method_option :help, aliases: '-h', type: :boolean,
71
+ desc: 'Display usage information'
72
+ method_option :context, aliases: '-c', type: :string,
73
+ desc: 'Path to context file'
74
+ method_option :output, aliases: '-o', type: :string,
75
+ default: './build',
76
+ desc: 'Output folder'
77
+ def build(*configPaths)
78
+ handleCommand(:build, configPaths, options)
79
+ end
80
+
81
+
82
+ desc 'deploy [CONFIGS...]', 'Deploy configuration'
83
+ method_option :help, aliases: '-h', type: :boolean,
84
+ desc: 'Display usage information'
85
+ method_option :state, aliases: '-s', type: :string,
86
+ desc: 'Path to the state file'
87
+ method_option :context, aliases: '-c', type: :string,
88
+ desc: 'Path to context file'
89
+ method_option :output, aliases: '-o', type: :string,
90
+ default: '/tmp or ./build',
91
+ desc: 'Output folder'
92
+ def deploy(*configPaths)
93
+ handleCommand(:deploy, configPaths, options)
94
+ end
95
+
96
+
97
+ desc 'cleanup [CONFIGS...]', 'In deployed infrastructure cleanup/delete unused things (eg. deployment leftover junk) (note this can be risky due to mistakes)'
98
+ method_option :help, aliases: '-h', type: :boolean,
99
+ desc: 'Display usage information'
100
+ method_option :state, aliases: '-s', type: :string,
101
+ desc: 'Path to the state file'
102
+ def cleanup(*configPaths)
103
+ handleCommand(:cleanup, configPaths, options)
104
+ end
105
+
106
+ desc 'types', 'List available types/plugins'
107
+ method_option :help, aliases: '-h', type: :boolean,
108
+ desc: 'Display usage information'
109
+ def types
110
+ handleCommand(:types, options)
111
+ end
112
+
113
+ =begin
114
+ # TODO
115
+ desc 'test [CONFIGS...]', 'Test whether deployed things work as expected'
116
+ method_option :help, aliases: '-h', type: :boolean,
117
+ desc: 'Display usage information'
118
+ method_option :load, aliases: '-l', type: :boolean,
119
+ desc: 'Run performance/load tests (might be dangerous as it can affect live users)'
120
+ method_option :chaos, aliases: '-c', type: :boolean,
121
+ desc: 'Test whether systems keep working while random things die (might be dangerous as it can affect live users due to injecting real faults)'
122
+ method_option :alerts, aliases: '-a', type: :boolean,
123
+ desc: 'Test failure conditions and whether alerts work (might be dangerous as it can affect live users due to injecting real faults)'
124
+ method_option :tools, aliases: '-t', type: :string, desc: 'Filter tools to use for testing'
125
+
126
+ def test(*configPaths)
127
+ handleCommand(:test, configPaths, options)
128
+ end
129
+
130
+ desc 'compare [CONFIGS...]', 'Show changes between local state and deployed things'
131
+ method_option :help, aliases: '-h', type: :boolean,
132
+ desc: 'Display usage information'
133
+ method_option :state, aliases: '-s', type: :string,
134
+ desc: 'Path to state file'
135
+ def compare(*configPaths)
136
+ handleCommand(:compare, configPaths, options)
137
+ end
138
+
139
+ =end
140
+
141
+ private
142
+
143
+ def handleCommand(name, *params)
144
+ if options[:help]
145
+ invoke :help, [name.to_s]
146
+ else
147
+ require_relative('commands/' + name.to_s)
148
+ Object.const_get('ConfigLMM::Commands::' + name.to_s.capitalize).new(*params).execute
149
+ end
150
+ rescue ArgumentError => e
151
+ $stderr.puts(e)
152
+ invoke :help, [name.to_s]
153
+ exit 1
154
+ end
155
+
156
+
157
+ def self.exit_on_failure?
158
+ true
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConfigLMM
4
+ class Command
5
+ # Execute this command
6
+ #
7
+ # @api public
8
+ def execute(*)
9
+ raise(NotImplementedError, "#{self.class}##{__method__} must be implemented")
10
+ end
11
+
12
+ # A readable, structured and beautiful logging for the terminal
13
+ #
14
+ # @see http://www.rubydoc.info/gems/tty-logger
15
+ #
16
+ # @api public
17
+ def logger
18
+ if @Logger.nil?
19
+ require 'tty-logger'
20
+ @Logger = TTY::Logger.new do |config|
21
+ yield(config)
22
+ end
23
+ end
24
+ @Logger
25
+ end
26
+
27
+ # The external commands runner
28
+ #
29
+ # @see http://www.rubydoc.info/gems/tty-command
30
+ #
31
+ # @api public
32
+ def command(**options)
33
+ if @Command.nil?
34
+ require 'tty-command'
35
+ @Command = TTY::Command.new(options)
36
+ end
37
+ @Command
38
+ end
39
+
40
+ # The interactive prompt
41
+ #
42
+ # @see http://www.rubydoc.info/gems/tty-prompt
43
+ #
44
+ # @api public
45
+ def prompt
46
+ if @Prompt.nil?
47
+ require 'tty-prompt'
48
+ @Prompt = TTY::Prompt.new
49
+ end
50
+ @Prompt
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'configsCommand'
4
+
5
+ module ConfigLMM
6
+ module Commands
7
+ class Build < ConfigsCommand
8
+ def processConfig(config, options)
9
+
10
+ config.each do |id, target|
11
+
12
+ target['Resources'].to_h.each do |id, target|
13
+ IO::ConfigList.processConfig(id, target, target[:Parent])
14
+ processBuild(IO::ConfigList.normalizeId(id), target, options)
15
+ end
16
+
17
+ processBuild(id, target, options)
18
+ end
19
+ prompt.ok('Build successful, artifacts are in ' + options['output'])
20
+ end
21
+
22
+ def processBuild(id, target, options)
23
+ providers = []
24
+ self.plugins.each do |pluginId, plugin|
25
+ if plugin.hasAction?(target['Type'], :build)
26
+ providers << plugin
27
+ end
28
+ end
29
+
30
+ if providers.empty?
31
+ logger.debug("Skipping ID=#{id} - Type=#{target['Type']}")
32
+ return
33
+ end
34
+
35
+ bestProvider = self.findBestProvider(providers)
36
+ invokeBuildAction(id, bestProvider, target, options)
37
+ end
38
+
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'configsCommand'
4
+
5
+ module ConfigLMM
6
+ module Commands
7
+ class Cleanup < ConfigsCommand
8
+
9
+ def processConfig(config, options)
10
+ plugins.each do |pluginId, plugin|
11
+ configs = {}
12
+ loadConfigs(plugin, config, configs)
13
+ plugin.cleanup(configs, state, context, options)
14
+ end
15
+ prompt.ok('Cleanup successful!')
16
+ end
17
+
18
+ def loadConfigs(plugin, config, configs)
19
+ config.each do |id, target|
20
+ loadConfigs(plugin, target['Resources'], configs) if target['Resources']
21
+ if plugin.hasAction?(target['Type'], :deploy)
22
+ configs[id] = target
23
+ end
24
+ end
25
+ configs
26
+ end
27
+
28
+ end
29
+ end
30
+ end