ConfigLMM 0.4.0 → 0.5.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 (227) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +34 -0
  3. data/CNAME +1 -0
  4. data/Examples/.lmm.state.yaml +159 -0
  5. data/Examples/ConfigLMM.mm.yaml +32 -0
  6. data/Examples/Implemented.mm.yaml +252 -4
  7. data/Examples/SmallBusiness.mm.yaml +492 -0
  8. data/Plugins/Apps/Answer/answer.lmm.rb +165 -0
  9. data/Plugins/Apps/Answer/answer@.service +40 -0
  10. data/Plugins/Apps/ArchiSteamFarm/ArchiSteamFarm.conf.erb +0 -3
  11. data/Plugins/Apps/ArchiSteamFarm/ArchiSteamFarm.lmm.rb +0 -1
  12. data/Plugins/Apps/Authentik/Authentik-ProxyOutpost.container +7 -1
  13. data/Plugins/Apps/Authentik/Authentik-Server.container +6 -1
  14. data/Plugins/Apps/Authentik/Authentik-Worker.container +6 -1
  15. data/Plugins/Apps/Authentik/Authentik.conf.erb +12 -7
  16. data/Plugins/Apps/Authentik/Authentik.lmm.rb +226 -61
  17. data/Plugins/Apps/BookStack/BookStack.conf.erb +0 -3
  18. data/Plugins/Apps/BookStack/BookStack.container +5 -0
  19. data/Plugins/Apps/BookStack/BookStack.lmm.rb +14 -3
  20. data/Plugins/Apps/Cassandra/Cassandra.lmm.rb +9 -19
  21. data/Plugins/Apps/ClickHouse/ClickHouse.container +28 -0
  22. data/Plugins/Apps/ClickHouse/ClickHouse.lmm.rb +113 -0
  23. data/Plugins/Apps/ClickHouse/Config/listen.yaml +2 -0
  24. data/Plugins/Apps/ClickHouse/Config/logger.yaml +8 -0
  25. data/Plugins/Apps/ClickHouse/Config/zookeepers.yaml +5 -0
  26. data/Plugins/Apps/ClickHouse/Connection.rb +96 -0
  27. data/Plugins/Apps/Discourse/Discourse-Sidekiq.container +5 -0
  28. data/Plugins/Apps/Discourse/Discourse.conf.erb +1 -4
  29. data/Plugins/Apps/Discourse/Discourse.container +4 -0
  30. data/Plugins/Apps/Discourse/Discourse.lmm.rb +116 -55
  31. data/Plugins/Apps/Dovecot/Dovecot.lmm.rb +74 -62
  32. data/Plugins/Apps/ERPNext/ERPNext-Frontend.container +6 -1
  33. data/Plugins/Apps/ERPNext/ERPNext-Queue.container +5 -0
  34. data/Plugins/Apps/ERPNext/ERPNext-Scheduler.container +5 -0
  35. data/Plugins/Apps/ERPNext/ERPNext-Websocket.container +6 -1
  36. data/Plugins/Apps/ERPNext/ERPNext.container +6 -1
  37. data/Plugins/Apps/ERPNext/ERPNext.lmm.rb +138 -127
  38. data/Plugins/Apps/GitLab/GitLab.container +6 -0
  39. data/Plugins/Apps/GitLab/GitLab.lmm.rb +43 -49
  40. data/Plugins/Apps/Homepage/Homepage.conf.erb +86 -0
  41. data/Plugins/Apps/Homepage/Homepage.container +19 -0
  42. data/Plugins/Apps/Homepage/Homepage.lmm.rb +54 -0
  43. data/Plugins/Apps/IPFS/IPFS.conf.erb +0 -3
  44. data/Plugins/Apps/IPFS/IPFS.lmm.rb +0 -1
  45. data/Plugins/Apps/InfluxDB/InfluxDB.conf.erb +0 -3
  46. data/Plugins/Apps/InfluxDB/InfluxDB.lmm.rb +0 -1
  47. data/Plugins/Apps/Jackett/Jackett.conf.erb +0 -3
  48. data/Plugins/Apps/Jackett/Jackett.lmm.rb +0 -1
  49. data/Plugins/Apps/Jellyfin/Jellyfin.conf.erb +0 -3
  50. data/Plugins/Apps/Jellyfin/Jellyfin.lmm.rb +0 -1
  51. data/Plugins/Apps/LetsEncrypt/LetsEncrypt.lmm.rb +49 -28
  52. data/Plugins/Apps/LibreTranslate/LibreTranslate.container +21 -0
  53. data/Plugins/Apps/LibreTranslate/LibreTranslate.lmm.rb +34 -0
  54. data/Plugins/Apps/Lobsters/Containerfile +81 -0
  55. data/Plugins/Apps/Lobsters/Lobsters-Tasks.container +26 -0
  56. data/Plugins/Apps/Lobsters/Lobsters.conf.erb +99 -0
  57. data/Plugins/Apps/Lobsters/Lobsters.container +27 -0
  58. data/Plugins/Apps/Lobsters/Lobsters.lmm.rb +196 -0
  59. data/Plugins/Apps/Lobsters/crontab +3 -0
  60. data/Plugins/Apps/Lobsters/database.yml +26 -0
  61. data/Plugins/Apps/Lobsters/entrypoint.sh +30 -0
  62. data/Plugins/Apps/Lobsters/generateCredentials.rb +19 -0
  63. data/Plugins/Apps/Lobsters/lobsters-cron.sh +25 -0
  64. data/Plugins/Apps/Lobsters/lobsters-daily.sh +23 -0
  65. data/Plugins/Apps/Lobsters/puma.rb +49 -0
  66. data/Plugins/Apps/MariaDB/Connection.rb +55 -0
  67. data/Plugins/Apps/MariaDB/MariaDB.lmm.rb +60 -53
  68. data/Plugins/Apps/Mastodon/Mastodon-Sidekiq.container +22 -0
  69. data/Plugins/Apps/Mastodon/Mastodon-Streaming.container +20 -0
  70. data/Plugins/Apps/Mastodon/Mastodon.conf.erb +34 -45
  71. data/Plugins/Apps/Mastodon/Mastodon.container +28 -0
  72. data/Plugins/Apps/Mastodon/Mastodon.lmm.rb +240 -5
  73. data/Plugins/Apps/Mastodon/configlmm.rake +30 -0
  74. data/Plugins/Apps/Mastodon/entrypoint.sh +16 -0
  75. data/Plugins/Apps/Matrix/Element.container +5 -0
  76. data/Plugins/Apps/Matrix/Matrix.conf.erb +2 -8
  77. data/Plugins/Apps/Matrix/Matrix.lmm.rb +100 -71
  78. data/Plugins/Apps/Matrix/Synapse.container +5 -0
  79. data/Plugins/Apps/Netdata/Netdata.conf.erb +0 -3
  80. data/Plugins/Apps/Netdata/Netdata.lmm.rb +0 -1
  81. data/Plugins/Apps/Nextcloud/Nextcloud.conf.erb +3 -4
  82. data/Plugins/Apps/Nextcloud/Nextcloud.lmm.rb +150 -68
  83. data/Plugins/Apps/Nextcloud/autoconfig.php +13 -0
  84. data/Plugins/Apps/Nextcloud/config.php +10 -1
  85. data/Plugins/Apps/Nextcloud/nextcloudcron.service +8 -0
  86. data/Plugins/Apps/Nextcloud/nextcloudcron.timer +10 -0
  87. data/Plugins/Apps/Nginx/Connection.rb +93 -0
  88. data/Plugins/Apps/Nginx/conf.d/configlmm.conf +50 -9
  89. data/Plugins/Apps/Nginx/conf.d/languages.conf +21 -0
  90. data/Plugins/Apps/Nginx/config-lmm/errors.conf +25 -20
  91. data/Plugins/Apps/Nginx/config-lmm/gateway-errors.conf +20 -0
  92. data/Plugins/Apps/Nginx/config-lmm/proxy.conf +1 -1
  93. data/Plugins/Apps/Nginx/main.conf.erb +7 -3
  94. data/Plugins/Apps/Nginx/nginx.conf +2 -2
  95. data/Plugins/Apps/Nginx/nginx.lmm.rb +99 -81
  96. data/Plugins/Apps/Nginx/proxy.conf.erb +11 -3
  97. data/Plugins/Apps/Odoo/Odoo.conf.erb +0 -3
  98. data/Plugins/Apps/Odoo/Odoo.container +5 -0
  99. data/Plugins/Apps/Odoo/Odoo.lmm.rb +4 -5
  100. data/Plugins/Apps/Ollama/Ollama.container +26 -0
  101. data/Plugins/Apps/Ollama/Ollama.lmm.rb +73 -0
  102. data/Plugins/Apps/OpenTelemetry/Config/config.yaml +704 -0
  103. data/Plugins/Apps/OpenTelemetry/OpenTelemetry.lmm.rb +154 -0
  104. data/Plugins/Apps/OpenVidu/Ingress.container +5 -0
  105. data/Plugins/Apps/OpenVidu/OpenVidu.conf.erb +0 -3
  106. data/Plugins/Apps/OpenVidu/OpenVidu.container +5 -0
  107. data/Plugins/Apps/OpenVidu/OpenVidu.lmm.rb +7 -3
  108. data/Plugins/Apps/OpenVidu/OpenViduCall.conf.erb +0 -3
  109. data/Plugins/Apps/OpenVidu/OpenViduCall.container +5 -0
  110. data/Plugins/Apps/PHP-FPM/Connection.rb +91 -0
  111. data/Plugins/Apps/PHP-FPM/PHP-FPM.lmm.rb +31 -4
  112. data/Plugins/Apps/Peppermint/Peppermint.conf.erb +2 -5
  113. data/Plugins/Apps/Peppermint/Peppermint.container +5 -0
  114. data/Plugins/Apps/Peppermint/Peppermint.lmm.rb +29 -33
  115. data/Plugins/Apps/Perplexica/Perplexica.container +25 -0
  116. data/Plugins/Apps/Perplexica/Perplexica.lmm.rb +92 -0
  117. data/Plugins/Apps/Perplexica/config.toml +26 -0
  118. data/Plugins/Apps/Podman/Connection.rb +24 -0
  119. data/Plugins/Apps/Podman/Podman.lmm.rb +80 -0
  120. data/Plugins/Apps/Podman/storage.conf +6 -0
  121. data/Plugins/Apps/Postfix/Postfix.lmm.rb +242 -164
  122. data/Plugins/Apps/PostgreSQL/Connection.rb +97 -0
  123. data/Plugins/Apps/PostgreSQL/PostgreSQL.lmm.rb +184 -148
  124. data/Plugins/Apps/Pterodactyl/Pterodactyl.conf.erb +0 -3
  125. data/Plugins/Apps/Pterodactyl/Pterodactyl.lmm.rb +0 -2
  126. data/Plugins/Apps/Pterodactyl/Wings.conf.erb +0 -3
  127. data/Plugins/Apps/RVM/RVM.lmm.rb +57 -0
  128. data/Plugins/Apps/Roundcube/Roundcube.conf.erb +0 -3
  129. data/Plugins/Apps/Roundcube/Roundcube.lmm.rb +15 -19
  130. data/Plugins/Apps/SSH/SSH.lmm.rb +9 -15
  131. data/Plugins/Apps/SearXNG/SearXNG.container +22 -0
  132. data/Plugins/Apps/SearXNG/SearXNG.lmm.rb +79 -0
  133. data/Plugins/Apps/SearXNG/limiter.toml +40 -0
  134. data/Plugins/Apps/SearXNG/settings.yml +2 -0
  135. data/Plugins/Apps/SigNoz/Config/alerts.yml +11 -0
  136. data/Plugins/Apps/SigNoz/Config/otel-collector-config.yaml +110 -0
  137. data/Plugins/Apps/SigNoz/Config/otel-collector-opamp-config.yaml +1 -0
  138. data/Plugins/Apps/SigNoz/Config/prometheus.yml +18 -0
  139. data/Plugins/Apps/SigNoz/SigNoz-Collector.container +23 -0
  140. data/Plugins/Apps/SigNoz/SigNoz-Migrator.container +17 -0
  141. data/Plugins/Apps/SigNoz/SigNoz.conf.erb +61 -0
  142. data/Plugins/Apps/SigNoz/SigNoz.container +26 -0
  143. data/Plugins/Apps/SigNoz/SigNoz.lmm.rb +319 -0
  144. data/Plugins/Apps/Solr/log4j2.xml +89 -0
  145. data/Plugins/Apps/Solr/solr.lmm.rb +82 -0
  146. data/Plugins/Apps/Sunshine/Sunshine.conf.erb +0 -3
  147. data/Plugins/Apps/Sunshine/Sunshine.lmm.rb +0 -1
  148. data/Plugins/Apps/Tunnel/tunnel.lmm.rb +33 -37
  149. data/Plugins/Apps/UVdesk/UVdesk.conf.erb +0 -3
  150. data/Plugins/Apps/Umami/Umami.container +19 -0
  151. data/Plugins/Apps/Umami/Umami.lmm.rb +108 -0
  152. data/Plugins/Apps/Valkey/Valkey.lmm.rb +54 -42
  153. data/Plugins/Apps/Vaultwarden/Vaultwarden.conf.erb +9 -6
  154. data/Plugins/Apps/Vaultwarden/Vaultwarden.container +7 -1
  155. data/Plugins/Apps/Vaultwarden/Vaultwarden.lmm.rb +64 -29
  156. data/Plugins/Apps/Wiki.js/Wiki.js.conf.erb +1 -4
  157. data/Plugins/Apps/Wiki.js/Wiki.js.container +5 -0
  158. data/Plugins/Apps/Wiki.js/Wiki.js.lmm.rb +31 -37
  159. data/Plugins/Apps/YaCy/YaCy.conf.erb +93 -0
  160. data/Plugins/Apps/YaCy/YaCy.container +21 -0
  161. data/Plugins/Apps/YaCy/YaCy.lmm.rb +160 -0
  162. data/Plugins/Apps/ZooKeeper/ZooKeeper.container +24 -0
  163. data/Plugins/Apps/ZooKeeper/ZooKeeper.lmm.rb +68 -0
  164. data/Plugins/Apps/bitmagnet/bitmagnet.conf.erb +0 -3
  165. data/Plugins/Apps/bitmagnet/bitmagnet.lmm.rb +0 -1
  166. data/Plugins/Apps/gollum/gollum.conf.erb +2 -4
  167. data/Plugins/Apps/gollum/gollum.container +6 -0
  168. data/Plugins/Apps/gollum/gollum.lmm.rb +51 -50
  169. data/Plugins/Apps/llama.cpp/llama.cpp.container +28 -0
  170. data/Plugins/Apps/llama.cpp/llama.cpp.lmm.rb +90 -0
  171. data/Plugins/Apps/vLLM/vLLM.container +32 -0
  172. data/Plugins/Apps/vLLM/vLLM.lmm.rb +89 -0
  173. data/Plugins/OS/General/Utils.lmm.rb +26 -0
  174. data/Plugins/OS/Linux/Connection.rb +472 -0
  175. data/Plugins/OS/Linux/Debian/preseed.cfg.erb +25 -6
  176. data/Plugins/OS/Linux/Flavours.yaml +13 -0
  177. data/Plugins/OS/Linux/Grub/grub.cfg +10 -0
  178. data/Plugins/OS/Linux/HTTP.rb +32 -0
  179. data/Plugins/OS/Linux/Linux.lmm.rb +533 -187
  180. data/Plugins/OS/Linux/Packages.yaml +20 -1
  181. data/Plugins/OS/Linux/Services.yaml +8 -0
  182. data/Plugins/OS/Linux/Shell.rb +70 -0
  183. data/Plugins/OS/Linux/Syslinux/default +8 -0
  184. data/Plugins/OS/Linux/WireGuard/WireGuard.lmm.rb +83 -59
  185. data/Plugins/OS/Linux/WireGuard/wg0.conf.erb +3 -0
  186. data/Plugins/OS/Linux/openSUSE/autoinst.xml.erb +29 -3
  187. data/Plugins/OS/Linux/systemd/systemd.lmm.rb +13 -11
  188. data/Plugins/OS/Routers/Aruba/ArubaInstant.lmm.rb +6 -5
  189. data/Plugins/Platforms/GitHub.lmm.rb +73 -28
  190. data/Plugins/Platforms/GoDaddy/GoDaddy.lmm.rb +9 -6
  191. data/Plugins/Platforms/Proxmox/Proxmox.lmm.rb +402 -0
  192. data/Plugins/Platforms/Proxmox/XTerm.rb +321 -0
  193. data/Plugins/Platforms/libvirt/libvirt.lmm.rb +38 -13
  194. data/Plugins/Platforms/porkbun.lmm.rb +12 -2
  195. data/Plugins/Platforms/porkbun_spec.rb +2 -2
  196. data/Plugins/Services/DNS/AmberBit.lmm.rb +1 -1
  197. data/Plugins/Services/DNS/ArubaItDNS.lmm.rb +1 -1
  198. data/Plugins/Services/DNS/NICLV.lmm.rb +1 -1
  199. data/Plugins/Services/DNS/PowerDNS.lmm.rb +70 -68
  200. data/Plugins/Services/DNS/tonic.lmm.rb +22 -12
  201. data/lib/ConfigLMM/Framework/plugins/dns.rb +4 -3
  202. data/lib/ConfigLMM/Framework/plugins/linuxApp.rb +145 -184
  203. data/lib/ConfigLMM/Framework/plugins/nginxApp.rb +34 -17
  204. data/lib/ConfigLMM/Framework/plugins/plugin.rb +53 -181
  205. data/lib/ConfigLMM/Framework/plugins/store.rb +4 -4
  206. data/lib/ConfigLMM/Framework/variables.rb +75 -0
  207. data/lib/ConfigLMM/Framework.rb +1 -0
  208. data/lib/ConfigLMM/cli.rb +12 -6
  209. data/lib/ConfigLMM/commands/configsCommand.rb +37 -6
  210. data/lib/ConfigLMM/commands/diff.rb +33 -9
  211. data/lib/ConfigLMM/context.rb +22 -3
  212. data/lib/ConfigLMM/io/configList.rb +82 -6
  213. data/lib/ConfigLMM/io/connection.rb +143 -0
  214. data/lib/ConfigLMM/io/dhcp.rb +330 -0
  215. data/lib/ConfigLMM/io/http.rb +78 -0
  216. data/lib/ConfigLMM/io/local.rb +207 -0
  217. data/lib/ConfigLMM/io/pxe.rb +92 -0
  218. data/lib/ConfigLMM/io/ssh.rb +156 -0
  219. data/lib/ConfigLMM/io/tftp.rb +105 -0
  220. data/lib/ConfigLMM/io.rb +2 -0
  221. data/lib/ConfigLMM/secrets/envStore.rb +39 -0
  222. data/lib/ConfigLMM/secrets/fileStore.rb +43 -0
  223. data/lib/ConfigLMM/state.rb +2 -1
  224. data/lib/ConfigLMM/version.rb +2 -1
  225. data/lib/ConfigLMM.rb +1 -0
  226. data/{Examples → scripts}/configlmmAuth.sh +7 -5
  227. metadata +205 -8
@@ -49,10 +49,10 @@ module ConfigLMM
49
49
  def actionPowerDNSDeploy(id, target, activeState, context, options)
50
50
  #actionPowerDNSDiff(id, target, activeState, context, options)
51
51
 
52
- deploySettings(target, activeState, options)
52
+ deploySettings(target, activeState, context, options)
53
53
  connect(id, target, activeState, context, options) do |host, port, key|
54
54
  if target['TSIG']
55
- updateTSIG(host, port, key, target['TSIG'])
55
+ updateTSIG(host, port, key, target, context)
56
56
  end
57
57
  if target['DNS']
58
58
  updateDNS(host, port, key, target['DNS'])
@@ -64,19 +64,23 @@ module ConfigLMM
64
64
  end
65
65
 
66
66
  def cleanup(configs, state, context, options)
67
- cleanupType(:PowerDNS, configs, state, context, options) do |item, id, state, context, options, ssh|
68
- if item['Deploy']
69
- Framework::LinuxApp.stopService(SERVICE_NAME, ssh, options[:dry])
70
- Framework::LinuxApp.firewallRemoveService('dns', ssh, options[:dry])
71
- Framework::LinuxApp.removePackage(PACKAGE_NAME, ssh, options[:dry])
72
-
73
- state.item(id)['Status'] = State::STATUS_DELETED unless options[:dry]
74
-
75
- if options[:destroy]
76
- item['Database'] ||= {}
77
- PostgreSQL.dropUserAndDB(item['Database'], USER, ssh, options[:dry])
78
- rm('/etc/pdns', options[:dry], ssh)
79
- state.item(id)['Status'] = State::STATUS_DESTROYED unless options[:dry]
67
+ cleanupType(:PowerDNS, configs, state, context, options) do |item, id, state, context, options, connection|
68
+ if item['Config']['Deploy']
69
+ Linux.withConnection(connection) do |linuxConnection|
70
+ linuxConnection.stopService(SERVICE_NAME, options)
71
+ linuxConnection.firewallRemoveService('dns', options)
72
+ linuxConnection.removePackage(PACKAGE_NAME, options)
73
+
74
+ state.item(id)['Status'] = State::STATUS_DELETED unless options[:dry]
75
+
76
+ if options[:destroy]
77
+ item['Config']['Database'] ||= {}
78
+ PostgreSQL.withConnection(item['Config']['Database'], linuxConnection) do |connectionDB|
79
+ connectionDB.dropUserAndDB(USER, options)
80
+ end
81
+ linuxConnection.rm('/etc/pdns', options[:dry])
82
+ state.item(id)['Status'] = State::STATUS_DESTROYED unless options[:dry]
83
+ end
80
84
  end
81
85
  else
82
86
  # TODO
@@ -129,7 +133,6 @@ module ConfigLMM
129
133
  if !dns.list_zones(server).map { |zone| zone['name'].downcase }.include?(canonicalDomain.downcase)
130
134
  dns.create_zone(server, canonicalDomain, [], { kind: 'Native' }.update(info['!'].to_h))
131
135
  elsif !info['!'].to_h.empty?
132
- puts ({ kind: 'Native' }.update(info['!'].to_h).inspect)
133
136
  dns.update_zone(server, canonicalDomain, { kind: 'Native' }.update(info['!'].to_h))
134
137
  end
135
138
 
@@ -141,7 +144,7 @@ module ConfigLMM
141
144
  next if name == '!'
142
145
  fullName = Addressable::IDNA.to_ascii(name) + '.' + Addressable::IDNA.to_ascii(domain) + '.'
143
146
  fullName = Addressable::IDNA.to_ascii(domain) + '.' if name == '@'
144
- self.processDNS(domain, data).each do |type, records|
147
+ self.processDNS(domain, data, context).each do |type, records|
145
148
  #remove += removeConflicting(zone, fullName, type)
146
149
  rrset = {
147
150
  name: fullName,
@@ -151,7 +154,7 @@ module ConfigLMM
151
154
  records: []
152
155
  }
153
156
  records.each do |record|
154
- record[:content] = Addressable::IDNA.to_ascii(record[:content]) + '.' if type == 'CNAME' || type == 'ALIAS'
157
+ record[:content] = Addressable::IDNA.to_ascii(record[:content]) + '.' if type == 'CNAME' || type == 'ALIAS' || type == 'NS'
155
158
  if type == 'MX'
156
159
  priority, name = record[:content].split(' ')
157
160
  name = Addressable::IDNA.to_ascii(name) + '.'
@@ -180,16 +183,18 @@ module ConfigLMM
180
183
 
181
184
  end
182
185
 
183
- def updateTSIG(host, port, key, targetTSIG)
186
+ def updateTSIG(host, port, key, target, context)
184
187
  server = 'localhost'
185
188
  url = "http://#{host}:#{port}/api/v1/servers/#{server}/tsigkeys"
186
189
  headers = { 'X-Api-Key' => key }
187
- targetTSIG.each do |name, info|
190
+ target['TSIG'].each do |name, info|
188
191
  data = { name: name, algorithm: info['Algorithm'] }
189
192
  response = HTTP.headers(headers).post(url, json: data)
190
193
  if response.status == 201
191
194
  result = response.parse(:json)
192
- prompt.say("TSIG #{result['name']} key: #{result['key']}", :color => :magenta)
195
+ key = result['key']
196
+ context.secrets.store(target['SecretId'], "TSIG_#{result['name'].upcase}_KEY", key)
197
+ context.secrets.print("TSIG #{result['name']} Key", key)
193
198
  elsif response.status != 409
194
199
  prompt.say(response.body.to_s, :color => :red)
195
200
  raise 'Failed to create TSIG key!'
@@ -229,74 +234,71 @@ module ConfigLMM
229
234
  end
230
235
  end
231
236
 
232
- def deploySettings(target, activeState, options)
233
- if target['Location']
234
- uri = Addressable::URI.parse(target['Location'])
235
- params = {}
236
- params = CGI.parse(uri.query) if uri.query
237
- if uri.scheme == 'ssh' && !params.key?('host')
238
- self.class.sshStart(uri) do |ssh|
239
- target['Deploy'] = !!target['Settings'] unless target.key?('Deploy')
240
- activeState['Deploy'] = target['Deploy']
241
- if target['Deploy']
242
- Framework::LinuxApp.ensurePackages([PACKAGE_NAME], ssh)
243
- Framework::LinuxApp.ensureServiceAutoStartOverSSH(SERVICE_NAME, ssh)
244
- end
237
+ def deploySettings(target, activeState, context, options)
238
+ target['Deploy'] = !!target['Settings'] unless target.key?('Deploy')
239
+ if target['Deploy']
240
+ self.withConnection(target['Location'], target) do |connection|
241
+ Linux.withConnection(connection) do |linuxConnection|
242
+ linuxConnection.ensurePackages([PACKAGE_NAME], options)
243
+ linuxConnection.ensureServiceAutoStart(SERVICE_NAME, options)
245
244
  if target['Settings']
246
245
  prepareSettings(target)
247
- self.class.sshExec!(ssh, "mkdir -p #{CONFIG_DIR}")
248
- self.class.sshExec!(ssh, "sed -i 's|# include-dir=|include-dir=#{CONFIG_DIR}|' /etc/pdns/pdns.conf")
249
- ssh.scp.upload!(options['output'] + CONFIG_DIR + '/configlmm.conf', CONFIG_DIR + '/configlmm.conf')
246
+ linuxConnection.createDirs(options, CONFIG_DIR)
247
+ linuxConnection.fileReplace('/etc/pdns/pdns.conf', '# include-dir=', "include-dir=#{CONFIG_DIR}", options)
248
+ linuxConnection.upload(options['output'] + CONFIG_DIR + '/configlmm.conf', CONFIG_DIR + '/configlmm.conf', options)
250
249
  apiKeyFile = CONFIG_DIR + '/apiKey.conf'
251
- if !self.class.remoteFilePresent?(apiKeyFile, ssh)
252
- apiKey = ENV['POWERDNS_API_KEY']
253
- apiKey = SecureRandom.urlsafe_base64(60) unless apiKey
254
- self.class.sshExec!(ssh, " echo 'api-key=#{apiKey}' > #{apiKeyFile}")
255
- self.class.sshExec!(ssh, " chown #{USER}:#{USER} #{apiKeyFile}")
256
- self.class.sshExec!(ssh, " chmod 400 #{apiKeyFile}")
257
- prompt.say("PowerDNS API Key: #{apiKey}", )
250
+ apiKey = context.secrets.load(target['SecretId'], 'POWERDNS_API_KEY')
251
+ if linuxConnection.filePresent?(apiKeyFile, options)
252
+ if !apiKey
253
+ if options['dry']
254
+ linuxConnection.exec("cat #{apiKeyFile} | grep api-key | cut -d '=' -f 2", false, options)
255
+ end
256
+ apiKey = linuxConnection.exec("cat #{apiKeyFile} | grep api-key | cut -d '=' -f 2", false, { **options, 'dry' => false }).strip
257
+ context.secrets.store(target['SecretId'], 'POWERDNS_API_KEY', apiKey)
258
+ end
259
+ else
260
+ if !apiKey
261
+ apiKey = SecureRandom.urlsafe_base64(60)
262
+ context.secrets.store(target['SecretId'], 'POWERDNS_API_KEY', apiKey)
263
+ context.secrets.print('PowerDNS API Key', apiKey)
264
+ end
265
+ linuxConnection.fileWrite(apiKeyFile, "api-key=#{apiKey}", options)
266
+ linuxConnection.setUserGroup(apiKeyFile, USER, USER, options)
267
+ linuxConnection.setPrivate(apiKeyFile, options)
268
+ end
269
+ if !target.key?('Database') || target['Database']
270
+ self.configurePostgreSQL(target['Settings'], linuxConnection, options)
258
271
  end
259
- self.configurePostgreSQL(target['Settings'], ssh)
260
- end
261
- if target['Deploy']
262
- Framework::LinuxApp.firewallAddServiceOverSSH('dns', ssh)
263
- Framework::LinuxApp.startServiceOverSSH(SERVICE_NAME, ssh)
264
- activeState['Status'] = State::STATUS_DEPLOYED
265
272
  end
273
+ linuxConnection.firewallAddService('dns', options)
274
+ linuxConnection.restartService(SERVICE_NAME, options)
266
275
  end
267
276
  end
268
- else
269
- # TODO
270
277
  end
271
278
  end
272
279
 
273
- def configurePostgreSQL(settings, ssh)
274
- password = SecureRandom.alphanumeric(20)
275
- if settings['gpgsql-host'] == 'localhost' || settings['gpgsql-host'].start_with?('/')
276
- PostgreSQL.createUserAndDBOverSSH(USER, password, ssh)
277
- PostgreSQL.importSQL(USER, USER, '/usr/share/doc/packages/pdns/schema.pgsql.sql', ssh)
278
- PostgreSQL.updateOwner(USER, USER, ssh)
279
- else
280
- self.class.sshStart("ssh://#{settings['gpgsql-host']}/") do |ssh|
281
- PostgreSQL.createUserAndDBOverSSH(USER, password, ssh)
282
- PostgreSQL.importSQL(USER, USER, '/usr/share/doc/packages/pdns/schema.pgsql.sql', ssh)
283
- PostgreSQL.updateOwner(USER, USER, ssh)
284
- end
280
+ def configurePostgreSQL(settings, linuxConnection, options)
281
+ dbSettings = {}
282
+ dbSettings['HostName'] = settings['gpgsql-host']
283
+ dbSettings['HostName'] = 'localhost' if dbSettings['HostName'].start_with?('/')
284
+ PostgreSQL.withConnection(dbSettings, linuxConnection) do |postgresConnection|
285
+ password = SecureRandom.alphanumeric(20)
286
+ postgresConnection.createUserAndDB(USER, password, options)
287
+ postgresConnection.importSQL(USER, USER, '/usr/share/doc/packages/pdns/schema.pgsql.sql', options)
288
+ postgresConnection.updateOwner(USER, USER, options)
285
289
  end
286
- password
287
290
  end
288
291
 
289
292
  def connect(id, target, activeState, context, options)
290
293
  host = DEFAULT_HOST
291
294
  port = DEFAULT_PORT
292
- key = ENV['POWERDNS_API_KEY']
293
- key = target['Key'] if target['Key']
295
+ key = context.secrets.load(target['SecretId'], 'POWERDNS_API_KEY')
294
296
  raise Framework::PluginProcessError.new('PowerDNS missing API key!') unless key
295
297
 
296
298
  sshServer = nil
297
299
  sshUser = nil
298
300
  sshPort = nil
299
- sshPassword = ENV['POWERDNS_SSH_PASSWORD']
301
+ sshPassword = context.secrets.load(target['SecretId'], 'POWERDNS_SSH_PASSWORD')
300
302
 
301
303
  if target['Location']
302
304
  uri = Addressable::URI.parse(target['Location'])
@@ -21,17 +21,26 @@ module ConfigLMM
21
21
  errors
22
22
  end
23
23
 
24
+ def getPassword(target, context)
25
+ tonicPassword = context.secrets.load(target['SecretId'], 'PASSWORD')
26
+ tonicPassword = context.secrets.load('TONIC', 'PASSWORD') if tonicPassword.nil?
27
+ raise Framework::PluginProcessError.new('Missing Tonic DNS password!') unless tonicPassword
28
+ tonicPassword
29
+ end
30
+
24
31
  def actionTonicDNSRefresh(id, target, activeState, context, options)
25
32
  domain = target['Domain'].split('.').first
26
33
  if domain.empty?
27
34
  raise Framework::PluginProcessError.new('Invalid Domain for ' + id)
28
35
  end
29
- activeState['Domain'] = target['Domain']
36
+
37
+ tonicPassword = getPassword(target, context)
38
+
30
39
  response = HTTP.post(EDIT_URL, :form => {
31
40
  command: 'editdns',
32
41
  error: 'badpass.htm',
33
42
  sld: domain,
34
- password: ENV['TONIC_PASSWORD'],
43
+ password: tonicPassword,
35
44
  'B1.x' => "40",
36
45
  'B1.y' => "20"
37
46
  })
@@ -50,15 +59,15 @@ module ConfigLMM
50
59
  raise Framework::PluginProcessError.new('Unexpected value in response for ' + id)
51
60
  end
52
61
  else
53
- raise Framework::PluginProcessError.new("Couldn't refresh " + id + "! Invalid TONIC_PASSWORD ?")
62
+ raise Framework::PluginProcessError.new("Couldn't refresh " + id + "! Invalid Tonic password?")
54
63
  end
55
64
  end
56
65
 
57
66
  def actionTonicDNSDiff(id, target, activeState, context, options)
58
- shouldMatch(id, 'Domain', 'Domain', target, activeState)
67
+ shouldMatch(id, activeState['Config'], 'Domain', target, 'Domain')
59
68
  nameservers = activeState['Nameservers']&.transform_keys { |ns| Addressable::IDNA.to_unicode(ns) }
60
69
  if target['Nameservers'] != nameservers
61
- @Diff.update({'Nameservers' => [target['Nameservers'], nameservers]})
70
+ @Diff.update({'Nameservers' => [nameservers, target['Nameservers']]})
62
71
  end
63
72
  end
64
73
 
@@ -73,11 +82,13 @@ module ConfigLMM
73
82
  hosts = target['Nameservers'].keys.map { |ns| Addressable::IDNA.to_ascii(ns) }
74
83
  addrs = target['Nameservers'].values
75
84
 
85
+ tonicPassword = getPassword(target, context)
86
+
76
87
  response = HTTP.post(EDIT_URL, :form => {
77
88
  command: 'editdns',
78
89
  error: 'badpass.htm',
79
90
  sld: domain,
80
- password: ENV['TONIC_PASSWORD'],
91
+ password: tonicPassword,
81
92
  'B1.x' => "40",
82
93
  'B1.y' => "20"
83
94
  })
@@ -105,18 +116,17 @@ module ConfigLMM
105
116
  'B1.y': 30
106
117
  })
107
118
 
108
- activeState['Domain'] = target['Domain']
109
- activeState['Nameservers'] = target['Nameservers']
110
-
111
119
  prompt.say(Nokogiri::HTML(response.to_s).at('//title/text()'))
120
+ activeState['Nameservers'] = target['Nameservers']
112
121
  end
113
122
  end
114
123
 
115
124
  def authenticate(actionMethod, target, activeState, context, options)
116
- authSecret = ENV['TONIC_PASSWORD']
125
+ authSecret = context.secrets.load(target['SecretId'], 'PASSWORD')
126
+ authSecret = context.secrets.load('TONIC', 'PASSWORD') if authSecret.nil?
117
127
  if authSecret.to_s.empty?
118
- prompt.say('Set your Tonic DNS password to TONIC_PASSWORD as Environment Variable')
119
- raise Framework::PluginPrerequisite.new('Need TONIC_PASSWORD')
128
+ prompt.say("Set your Tonic DNS password in #{target['SecretId']}_PASSWORD")
129
+ raise Framework::PluginPrerequisite.new('Need Tonic DNS password!')
120
130
  end
121
131
  true
122
132
  end
@@ -8,7 +8,7 @@ module ConfigLMM
8
8
  class DNS < Framework::Plugin
9
9
  DEFAULT_TTL = 600
10
10
 
11
- def processDNS(domain, items)
11
+ def processDNS(domain, items, context)
12
12
  records = {}
13
13
 
14
14
  if items.is_a?(Hash)
@@ -25,6 +25,7 @@ module ConfigLMM
25
25
  type, content = item.strip.split('=')
26
26
  content = domain if content == '@'
27
27
  content = self.class.externalIp if content == '@me'
28
+ content = Variables.stringEval(content, context)
28
29
  records[type] ||= []
29
30
  records[type] << { type: type, content: content, ttl: DEFAULT_TTL }
30
31
  end
@@ -32,13 +33,13 @@ module ConfigLMM
32
33
  records
33
34
  end
34
35
 
35
- def showManualDNSSteps(target, message)
36
+ def showManualDNSSteps(target, message, context)
36
37
  if !target['DNS'].to_h.empty?
37
38
  target['DNS'].each do |domain, data|
38
39
  yield(domain)
39
40
  prompt.say(message, :color => :magenta) if message
40
41
  data.each do |name, data|
41
- self.processDNS(domain, data).each do |type, records|
42
+ self.processDNS(domain, data, context).each do |type, records|
42
43
  records.each do |record|
43
44
  prompt.say(" * Type: #{record[:type]}\n Name: #{name}\n Content: #{record[:content]}", :color => :bold)
44
45
  end