ConfigLMM 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.yardopts +4 -0
- data/CHANGELOG.md +5 -0
- data/Examples/Android.mm.yaml +8 -0
- data/Examples/Apps/Blog.mm.yaml +7 -0
- data/Examples/Apps/Jellyfin.mm.yaml +3 -0
- data/Examples/Implemented.mm.yaml +155 -0
- data/Examples/Keys.ini +7 -0
- data/Examples/Linux.mm.yaml +16 -0
- data/Examples/Windows.mm.yaml +11 -0
- data/Examples/configlmmAuth.sh +26 -0
- data/Plugins/Apps/ArchiSteamFarm/ArchiSteamFarm.conf.erb +38 -0
- data/Plugins/Apps/ArchiSteamFarm/ArchiSteamFarm.lmm.rb +19 -0
- data/Plugins/Apps/IPFS/IPFS.conf.erb +44 -0
- data/Plugins/Apps/IPFS/IPFS.lmm.rb +23 -0
- data/Plugins/Apps/InfluxDB/InfluxDB.conf.erb +34 -0
- data/Plugins/Apps/InfluxDB/InfluxDB.lmm.rb +19 -0
- data/Plugins/Apps/Jackett/Jackett.conf.erb +38 -0
- data/Plugins/Apps/Jackett/Jackett.lmm.rb +19 -0
- data/Plugins/Apps/Jellyfin/Jellyfin.conf.erb +59 -0
- data/Plugins/Apps/Jellyfin/Jellyfin.lmm.rb +23 -0
- data/Plugins/Apps/Mastodon/Mastodon.conf.erb +81 -0
- data/Plugins/Apps/Mastodon/Mastodon.lmm.rb +23 -0
- data/Plugins/Apps/Matrix/Matrix.conf.erb +36 -0
- data/Plugins/Apps/Matrix/Matrix.lmm.rb +23 -0
- data/Plugins/Apps/Netdata/Netdata.conf.erb +37 -0
- data/Plugins/Apps/Netdata/Netdata.lmm.rb +23 -0
- data/Plugins/Apps/Nextcloud/Nextcloud.conf.erb +165 -0
- data/Plugins/Apps/Nextcloud/Nextcloud.lmm.rb +23 -0
- data/Plugins/Apps/Nginx/config-lmm/errors.conf +31 -0
- data/Plugins/Apps/Nginx/config-lmm/private.conf +6 -0
- data/Plugins/Apps/Nginx/config-lmm/proxy.conf +15 -0
- data/Plugins/Apps/Nginx/config-lmm/public.conf +3 -0
- data/Plugins/Apps/Nginx/config-lmm/ssl.conf +18 -0
- data/Plugins/Apps/Nginx/main.conf +30 -0
- data/Plugins/Apps/Nginx/nginx.conf +90 -0
- data/Plugins/Apps/Nginx/nginx.lmm.rb +62 -0
- data/Plugins/Apps/Nginx/proxy.conf.erb +31 -0
- data/Plugins/Apps/Odoo/Odoo.conf.erb +44 -0
- data/Plugins/Apps/Odoo/Odoo.lmm.rb +23 -0
- data/Plugins/Apps/Pterodactyl/Pterodactyl.conf.erb +50 -0
- data/Plugins/Apps/Pterodactyl/Pterodactyl.lmm.rb +30 -0
- data/Plugins/Apps/Pterodactyl/Wings.conf.erb +38 -0
- data/Plugins/Apps/Sunshine/Sunshine.conf.erb +31 -0
- data/Plugins/Apps/Sunshine/Sunshine.lmm.rb +21 -0
- data/Plugins/Apps/Vaultwarden/Vaultwarden.conf.erb +48 -0
- data/Plugins/Apps/Vaultwarden/Vaultwarden.lmm.rb +25 -0
- data/Plugins/Apps/bitmagnet/bitmagnet.conf.erb +35 -0
- data/Plugins/Apps/bitmagnet/bitmagnet.lmm.rb +19 -0
- data/Plugins/Apps/gollum/config.ru +11 -0
- data/Plugins/Apps/gollum/gollum.conf.erb +41 -0
- data/Plugins/Apps/gollum/gollum.lmm.rb +52 -0
- data/Plugins/OS/Linux.lmm.rb +64 -0
- data/Plugins/OS/Routers/Aruba/ArubaInstant.lmm.rb +144 -0
- data/Plugins/Platforms/GitHub.lmm.rb +57 -0
- data/Plugins/Platforms/GoDaddy/GoDaddy.lmm.rb +83 -0
- data/Plugins/Platforms/GoDaddy/zone.txt.erb +13 -0
- data/Plugins/Platforms/porkbun.lmm.rb +129 -0
- data/Plugins/Platforms/porkbun_spec.rb +110 -0
- data/Plugins/Services/DNS/AmberBit.lmm.rb +14 -0
- data/Plugins/Services/DNS/ArubaItDNS.lmm.rb +14 -0
- data/Plugins/Services/DNS/NICLV.lmm.rb +18 -0
- data/Plugins/Services/DNS/PowerDNS.lmm.rb +261 -0
- data/Plugins/Services/DNS/tonic.lmm.rb +126 -0
- data/README.md +337 -0
- data/Rakefile +15 -0
- data/UNLICENSE +24 -0
- data/bin/configlmm +7 -0
- data/bin/console +11 -0
- data/bin/setup +8 -0
- data/lib/ConfigLMM/Framework/plugins/dns.rb +63 -0
- data/lib/ConfigLMM/Framework/plugins/errors.rb +23 -0
- data/lib/ConfigLMM/Framework/plugins/nginxApp.rb +55 -0
- data/lib/ConfigLMM/Framework/plugins/plugin.rb +167 -0
- data/lib/ConfigLMM/Framework/plugins/ssh.rb +37 -0
- data/lib/ConfigLMM/Framework/plugins/store.rb +57 -0
- data/lib/ConfigLMM/Framework/plugins.rb +5 -0
- data/lib/ConfigLMM/Framework/registrator.rb +32 -0
- data/lib/ConfigLMM/Framework.rb +9 -0
- data/lib/ConfigLMM/LMM/plugins.rb +5 -0
- data/lib/ConfigLMM/LMM.rb +8 -0
- data/lib/ConfigLMM/cli.rb +161 -0
- data/lib/ConfigLMM/command.rb +53 -0
- data/lib/ConfigLMM/commands/build.rb +41 -0
- data/lib/ConfigLMM/commands/cleanup.rb +30 -0
- data/lib/ConfigLMM/commands/configsCommand.rb +167 -0
- data/lib/ConfigLMM/commands/deploy.rb +39 -0
- data/lib/ConfigLMM/commands/diff.rb +45 -0
- data/lib/ConfigLMM/commands/list.rb +15 -0
- data/lib/ConfigLMM/commands/refresh.rb +46 -0
- data/lib/ConfigLMM/commands/types.rb +35 -0
- data/lib/ConfigLMM/commands/validate.rb +49 -0
- data/lib/ConfigLMM/context.rb +52 -0
- data/lib/ConfigLMM/io/configList.rb +98 -0
- data/lib/ConfigLMM/io/path.rb +48 -0
- data/lib/ConfigLMM/io/source.rb +47 -0
- data/lib/ConfigLMM/io.rb +2 -0
- data/lib/ConfigLMM/state.rb +78 -0
- data/lib/ConfigLMM/utils/filters.rb +126 -0
- data/lib/ConfigLMM/version.rb +5 -0
- data/lib/ConfigLMM.rb +6 -0
- data/sig/ConfigLMM.rbs +4 -0
- metadata +485 -0
data/README.md
ADDED
@@ -0,0 +1,337 @@
|
|
1
|
+
# ConfigLMM - Large Configuration Management Manager
|
2
|
+
|
3
|
+
## Manage The Management with ease!
|
4
|
+
|
5
|
+
You define how you want your applications/systems/containers/services/servers
|
6
|
+
to work without being vendor locked into any particular implementation or provider.
|
7
|
+
|
8
|
+
*ConfigLMM* will materialize this into whichever implementation you feel like using that day :)
|
9
|
+
|
10
|
+
**One Config to Rule Them All**:
|
11
|
+
|
12
|
+
* [Nginx](https://nginx.org/)
|
13
|
+
* [NGINX Unit](https://unit.nginx.org/)
|
14
|
+
* [Apache](https://apache.org/)
|
15
|
+
* [Docker](https://www.docker.com/)
|
16
|
+
* [Podman](https://podman.io/)
|
17
|
+
* [Kubernetes](https://kubernetes.io/)
|
18
|
+
* [Ansible](https://www.ansible.com/)
|
19
|
+
* [Chef](https://www.chef.io/)
|
20
|
+
* [Fluxcd](https://fluxcd.io/)
|
21
|
+
* [GitLab CI/CD](https://helm.sh/)
|
22
|
+
* [Helm](https://helm.sh/)
|
23
|
+
* [Puppet](https://www.puppet.com/)
|
24
|
+
* [Salt](https://saltproject.io/)
|
25
|
+
* [Spinnaker](https://spinnaker.io/)
|
26
|
+
* [Terraform](https://www.terraform.io/)
|
27
|
+
* [Amazon Web Services (AWS)](https://aws.amazon.com/)
|
28
|
+
* [DigitalOcean](https://www.digitalocean.com/)
|
29
|
+
* [Google Cloud](https://cloud.google.com/)
|
30
|
+
* [Microsoft Azure](https://azure.microsoft.com/)
|
31
|
+
* [Oracle Cloud Infrastructure (OCI)](https://www.oracle.com/cloud/)
|
32
|
+
* [OpenStack](https://www.openstack.org/)
|
33
|
+
* [VirtualBox](https://www.virtualbox.org/)
|
34
|
+
* [Chaos Monkey](https://github.com/Netflix/chaosmonkey)
|
35
|
+
* [Chaos Mesh](https://chaos-mesh.org/)
|
36
|
+
* [Cypress](https://www.cypress.io/)
|
37
|
+
* [Puppeteer](https://pptr.dev/)
|
38
|
+
* [Testsigma](https://testsigma.com/)
|
39
|
+
* [Selenium](https://www.selenium.dev/)
|
40
|
+
* [Greenbone Vulnerability Management (GVM/OpenVAS)](https://community.greenbone.net/)
|
41
|
+
* [Grype](https://github.com/anchore/grype)
|
42
|
+
* [Metasploit](https://www.metasploit.com/)
|
43
|
+
* [OpenCost](https://www.opencost.io/)
|
44
|
+
* [MSYS2](https://www.msys2.org/)
|
45
|
+
* [libvirt](https://libvirt.org/)
|
46
|
+
* [systemd](https://systemd.io/)
|
47
|
+
* [Wine](https://www.winehq.org/)
|
48
|
+
* [OpenEmbedded](https://www.openembedded.org/)
|
49
|
+
* [Yocto Project](https://www.yoctoproject.org/)
|
50
|
+
* [Nix](https://nixos.org/)
|
51
|
+
* [FreeBSD](https://www.freebsd.org/)
|
52
|
+
* [LineageOS](https://lineageos.org/)
|
53
|
+
* Any Cloud Provider
|
54
|
+
* Any kind of software (eg. [KDE](https://kde.org/), )
|
55
|
+
* Baremetal - your own host/VMs/VPS
|
56
|
+
* And everything else
|
57
|
+
|
58
|
+
The true [GitOps](https://en.wikipedia.org/wiki/DevOps#GitOps)/DevOps/DevSecOps/[TestOps](https://en.wikipedia.org/wiki/TestOps)/SysOps/[AIOps](https://en.wikipedia.org/wiki/Artificial_Intelligence_for_IT_Operations)[DataOps](https://en.wikipedia.org/wiki/DataOps) which I call AllTheOps :)
|
59
|
+
|
60
|
+
## Benefits
|
61
|
+
|
62
|
+
* Compare performance and price among different providers
|
63
|
+
* Host different services on different providers
|
64
|
+
* Migrate from local Docker to AWS Lambda and back to on-premises Kubernetes :)
|
65
|
+
* Move your applications across operating systems (eg. Windows to Linux etc)
|
66
|
+
* Easily and quickly switch between different implementations like from Apache to Nginx and so on
|
67
|
+
* Try out and compare different software easily (eg. reverse proxies, configuration management software etc)
|
68
|
+
* Provision new baremetal host with several VMs where each host bunch of Docker containers with multiple services inside
|
69
|
+
* Configure different devices (eg. IoT, routers, smartphones, coffee machines, fridges) and environments (eg. Wine, MSYS2, WSL, chroot, raw images) and a lot of other things
|
70
|
+
* Reuse configuration among different services
|
71
|
+
* Automatically follow best practises and secure by default without having to know anything about that
|
72
|
+
* Fully test (functionality/integration/end-to-end, load/performance and alerts/monitoring) all deployed infrastructure and applications
|
73
|
+
* Scan all your infrastructure for vulnerabilities and insecure configuration
|
74
|
+
* Practise [chaos engineering](https://en.wikipedia.org/wiki/Chaos_engineering) by testing how well systems handle various faults (eg. you have RAID1 does dropping a disk really doesn't affect applications? or terminating one application instance or database or even whole region)
|
75
|
+
* Automatically cleanup unused resources and other unneeded things
|
76
|
+
* Don't be limited with what your Platform Provider tools (CLIs/SDKs/APIs) support (eg. configure things thru Web UI portal if there's no other option)
|
77
|
+
* Anything else you can think of
|
78
|
+
|
79
|
+
Are you wondering if so many features won't make this unbearably complicated and unmaintainable?
|
80
|
+
|
81
|
+
I don't think so and this project will try to show that :) In fact I think most of existing
|
82
|
+
tools are overly complex. Think about Helm Charts/CloudFormation/Kubernetes/Puppet and such.
|
83
|
+
|
84
|
+
While most tools use declarative configuration I think they still got it wrong
|
85
|
+
because they are too low level by asking you to define *HOW* to accomplish target state while I think
|
86
|
+
configuration should just describe what you *WANT* the target state to be :)
|
87
|
+
|
88
|
+
So with *ConfigLMM* you only define what you *WANT* but don't describe *HOW* to accomplish that.
|
89
|
+
|
90
|
+
Some examples with idea of defining "*WHAT I WANT*":
|
91
|
+
|
92
|
+
* I need "*THESE*" files to be at "*MYDOMAIN*" (I don't even care where it runs just make it happen)
|
93
|
+
* "*THIS*" software hosted on "*MY*" VPS using "nginx" and "Puma" (yes I do have some preferences)
|
94
|
+
* run "*THIS*" container on "*FRIENDS*" Google Cloud account in "*THOSE*" regions
|
95
|
+
* I need "*THESE*" fonts on "*ALL*" my machines
|
96
|
+
|
97
|
+
I call this intention based configuration which is used by *ConfigLMM* and it also follows convention over configuration paradigm.
|
98
|
+
|
99
|
+
PS. Looks like I'm not only one thinking this way, see [RFC 9315 - Intent-Based Networking](https://www.ietf.org/rfc/rfc9315.html).
|
100
|
+
So essentially you can think of *ConfigLMM* as loose implementation of that RFC but even more because not only Networking part.
|
101
|
+
|
102
|
+
### Still not sold?
|
103
|
+
|
104
|
+
Then consider this scenario:
|
105
|
+
|
106
|
+
* Your brother who is a gamer bought new laptop which came with pre-installed Ubuntu
|
107
|
+
* Your mom bought Android smartphone which is her first one ever
|
108
|
+
* Your dad wants to start writing a blog and he cares deeply about his data and privacy
|
109
|
+
* Your friend who works at IoT company is looking into how to optimize company's infrastructure/software stack
|
110
|
+
|
111
|
+
So currently how would you make life easier/better for your family and friends(s)?
|
112
|
+
|
113
|
+
* Let them struggle on their own?
|
114
|
+
* Install and configure everything yourself? If so are you following best practices, with security and backups in mind? How sad your dad would be if blog stopped working? How much of your time this would take?
|
115
|
+
|
116
|
+
Let's have a meeting and find out what they actually want to do with their devices.
|
117
|
+
|
118
|
+
* Brother: I want to play Fortnite.
|
119
|
+
* Mom: Oh I don't know anything about this.
|
120
|
+
* Dad: I want to share some private articles with few friends but I don't want to give my data to [Big Tech](https://en.wikipedia.org/wiki/Big_Tech)!
|
121
|
+
* Friend: So my company has thousands of IoT devices that need firmware updates and we want to modernize/optimize our homegrown solution/control plane that has grown over many years to unimaginable complexity and has become quite fragile and thus making any changes is very risky/hard/slow.
|
122
|
+
|
123
|
+
Okay so now that we have an idea what we need we can start making it happen.
|
124
|
+
But do you know all the things that are needed to accomplish these goals? Your friend???
|
125
|
+
|
126
|
+
For brother:
|
127
|
+
|
128
|
+
* Fortnite - uses [kernel-level anti-cheat](https://lutris.net/games/fortnite/) so this rules out all non-Windows OS'es
|
129
|
+
* Need to install Windows, [Steam](https://store.steampowered.com/about/), Fortnite and his other favorite games
|
130
|
+
* You might not want ads/telemetry enabled on his Windows so need to disable those aswell
|
131
|
+
* Probably best to use privacy respecting browser
|
132
|
+
* Configure and install bunch of other things
|
133
|
+
|
134
|
+
For mom:
|
135
|
+
|
136
|
+
* You know she'll struggle with finding and installing her favorite apps so you want to preinstall those
|
137
|
+
* You might want to remove/uninstall some of already preinstalled apps because they might confuse her
|
138
|
+
* There are some settings that are not good preference for her so you want to change those aswell
|
139
|
+
|
140
|
+
For dad:
|
141
|
+
|
142
|
+
* Need some place to host blog that is not Big Tech
|
143
|
+
* Need authentication (maybe with user management?) so that he can share his private articles to friends
|
144
|
+
* For blog:
|
145
|
+
|
146
|
+
* Secure configuration and keeping up with new vulnerabilities (very common for blog software)
|
147
|
+
* Automatic backups
|
148
|
+
* Monitoring/Alerts
|
149
|
+
* Intrusion detection? What if someone gains access and posts bunch of spam there?
|
150
|
+
|
151
|
+
For friend:
|
152
|
+
|
153
|
+
*Uhm...* Yeah unless you've spent years working with IoT it's unlikely that you can help him there much.
|
154
|
+
|
155
|
+
I don't know about you but for me this all looks like *A LOT* of work.
|
156
|
+
|
157
|
+
So let's just move to the future and use *ConfigLMM* to solve all these problems :)
|
158
|
+
|
159
|
+
By using *ConfigLMM* you can create a configuration (even work together on it with family) that will satisfy everyone's needs and then make it all happen like *MAGIC* (just what they think it is)
|
160
|
+
|
161
|
+
So let's take a look at it:
|
162
|
+
|
163
|
+
```yaml
|
164
|
+
BrotherComputer:
|
165
|
+
Type: Windows
|
166
|
+
Managed: yes
|
167
|
+
Apps:
|
168
|
+
- Steam
|
169
|
+
- Fortnite
|
170
|
+
- Roblox
|
171
|
+
- Minecraft
|
172
|
+
- Firefox
|
173
|
+
|
174
|
+
MomPhone:
|
175
|
+
Type: Android
|
176
|
+
Settings:
|
177
|
+
HomeScreen: With App drawer
|
178
|
+
Apps:
|
179
|
+
- Duolingo
|
180
|
+
Remove:
|
181
|
+
- CandyCrush
|
182
|
+
|
183
|
+
DadBlog:
|
184
|
+
# In separate context file, there is specified "Dislikes: Big Tech"
|
185
|
+
Type: Blog
|
186
|
+
Feature: User Management
|
187
|
+
|
188
|
+
Friend:
|
189
|
+
# Omitted for brevity but yes ConfigLMM would be able to configure even that
|
190
|
+
```
|
191
|
+
|
192
|
+
Q: Wait what, is this all, *the WHOLE* config? *Yep, exactly like it should be, no more, no less :)*
|
193
|
+
|
194
|
+
Q: Then *WHY* have I been writing gazillion of bash scripts and thousands of Puppet/Kubernetes/[CDK](https://aws.amazon.com/cdk/) code lines? *For years I have been wondering the same*
|
195
|
+
|
196
|
+
Q: But what about friend how will I know how to write such config? You don't need to know how but just tell him to use *ConfigLMM* and his company's development team will spend some time creating it.
|
197
|
+
|
198
|
+
Q: How is this even possible? *MAGIC! See Implementation section for more details but generally you don't even need to care how*
|
199
|
+
|
200
|
+
## Back to The Reality
|
201
|
+
|
202
|
+
Well unfortunately what I just described is not really implemented yet.
|
203
|
+
|
204
|
+
This is a massive project and no matter how much I want to build it - it's not realistic that I can implement it all on my own.
|
205
|
+
|
206
|
+
And this is why I'm proposing this to be a community driven project where all of us help each other by implementing some parts of it.
|
207
|
+
|
208
|
+
When thinking about all of us together then it will save a lot of time for many of us. Especially as new Apps we want to host and configure just keeps growing.
|
209
|
+
|
210
|
+
Also maybe things you want to configure are already implemented so take a look at [Examples/Implemented.mm.yaml](/Examples/Implemented.mm.yaml) and see what we already have! :)
|
211
|
+
|
212
|
+
So I ask you to try it out (you can run `confilmm types` to see what is implemented), submit your issues and Pull Requests. I definitely need your and everyone's help to achieve this project's goal.
|
213
|
+
|
214
|
+
## Installation
|
215
|
+
|
216
|
+
First you need to have Ruby and RubyGems. Then you can install it with:
|
217
|
+
|
218
|
+
$ gem install ConfigLMM
|
219
|
+
|
220
|
+
## Usage
|
221
|
+
|
222
|
+
Create yaml file with desired config, eg.
|
223
|
+
```yaml
|
224
|
+
Wiki:
|
225
|
+
Type: Gollum
|
226
|
+
Domain: wiki.example.to
|
227
|
+
CertName: Gollum
|
228
|
+
Resources:
|
229
|
+
NS:
|
230
|
+
Type: TonicDNS
|
231
|
+
Domain: example.to
|
232
|
+
Nameservers:
|
233
|
+
ns.example.to: 192.168.5.5
|
234
|
+
DNS:
|
235
|
+
Type: PowerDNS
|
236
|
+
DNS:
|
237
|
+
example.to:
|
238
|
+
wiki: CNAME=@ # `@` means point it to the domain root
|
239
|
+
'@': A=@me # first `@` means domain root and `@me` means current external IP
|
240
|
+
```
|
241
|
+
|
242
|
+
Then deploy it and let the magic happen!
|
243
|
+
```
|
244
|
+
$ configlmm help
|
245
|
+
Commands:
|
246
|
+
configlmm build [CONFIGS...] # Build configuration in deployable form
|
247
|
+
configlmm deploy [CONFIGS...] # Deploy configuration
|
248
|
+
configlmm diff [CONFIGS...] # Show changes that will be applied with next deploy
|
249
|
+
configlmm help [COMMAND] # Describe available commands or one specific command
|
250
|
+
configlmm list [CONFIGS...] # List things
|
251
|
+
configlmm refresh [CONFIGS...] # Update local state to match deployed things
|
252
|
+
configlmm validate [CONFIGS...] # Check whether the configuration is valid
|
253
|
+
configlmm version # Show program's version
|
254
|
+
|
255
|
+
Options:
|
256
|
+
[--level=LEVEL] # Logging level to use
|
257
|
+
# Default: info
|
258
|
+
# Possible values: debug, info, warn, error
|
259
|
+
-n, [--dry], [--no-dry], [--skip-dry] # Only show actions without performing
|
260
|
+
|
261
|
+
$ configlmm deploy config.mm.yaml
|
262
|
+
Deploying...
|
263
|
+
Deploying NS: TonicDNS
|
264
|
+
Tonic - Successful DNS Change
|
265
|
+
Deploying DNS: PowerDNS
|
266
|
+
Deploying Wiki: Gollum
|
267
|
+
Deploy successful!
|
268
|
+
```
|
269
|
+
|
270
|
+
## FAQ
|
271
|
+
|
272
|
+
**Q: Why name it "*Large*"? Why "*L*" is after Config in *ConfigLMM*?**
|
273
|
+
|
274
|
+
To be a pun of [LLM](https://en.wikipedia.org/wiki/Large_language_model) and like with a language model you don't need to write down every single detail. Also *ConfigLMM* is definitely smarter than LLMs :)
|
275
|
+
|
276
|
+
Another thing is that it really is quite *Large*/big project to accomplish this goal with so many features.
|
277
|
+
|
278
|
+
**Q: I already have infrastructure deployer/orchestrator that I love and don't want to change so this is useless for me?**
|
279
|
+
|
280
|
+
Not necessarily, for example you can use `configlmm build` feature to create configs and then use your own orchestrator to do actual provisioning/deployment (and even do additional customization on built configs).
|
281
|
+
|
282
|
+
**Q: Aren't this many features a bit too much?**
|
283
|
+
|
284
|
+
No :)
|
285
|
+
|
286
|
+
**Q: Is this actually doable?**
|
287
|
+
|
288
|
+
Yes :)
|
289
|
+
|
290
|
+
**Q: Are you crazy/insane?**
|
291
|
+
|
292
|
+
Yes :) But maybe everyone/whole world is by learning hundreds of different tools with different versions each with dozens of incompatible/conflicting options/flags and some with couple of configuration files aswell.
|
293
|
+
|
294
|
+
I think the complexity of that is insane and the amount of different tools only keeps growing.
|
295
|
+
|
296
|
+
Can you count how many different tools/programs have you used today/this week/month? What about in a year or in your whole life together?
|
297
|
+
|
298
|
+
|
299
|
+
## Implementation
|
300
|
+
|
301
|
+
To accomplish this functionality *ConfigLMM* consists of 3 main parts:
|
302
|
+
|
303
|
+
1. High level configuration file format (superset/abstraction) that describes your infrastructure intentions
|
304
|
+
2. Core Framework that holds *ConfigLMM* together
|
305
|
+
2. Plugins for different apps/services/systems which implement build/deploy logic using provided configuration
|
306
|
+
|
307
|
+
Note that this project is in very early development stage and so there won't really be API/spec stability for some while.
|
308
|
+
You might need to update your configuration as new versions are released and design iterated and improved with time.
|
309
|
+
Unfortunately that's the sad reality we live in and things can't always be perfect from the start :)
|
310
|
+
|
311
|
+
## Development
|
312
|
+
|
313
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
314
|
+
|
315
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
316
|
+
|
317
|
+
## Contributing
|
318
|
+
|
319
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/ConfigLMM/ConfigLMM.
|
320
|
+
Pretty Please! :)
|
321
|
+
|
322
|
+
### Implement a new Plugin
|
323
|
+
|
324
|
+
To implement a new Plugin, simply create a file with name `$pluginName.lmm.rb` and put it in respective category in `Plugins` folder.
|
325
|
+
|
326
|
+
Then in that file create a method with name `action#{pluginName}Deploy` and implement logic there. It will be loaded automatically so you don't need any other changes.
|
327
|
+
|
328
|
+
I highly recommend looking at existing plugins. Also you can copy and rename `porkbun.lmm.rb` to use as a base.
|
329
|
+
|
330
|
+
### Model Configuration for App/Service/System
|
331
|
+
|
332
|
+
Try to model your existing infrastructure with high level YAML and submit those under Examples folder.
|
333
|
+
|
334
|
+
This will allow us to come up with best design for configuration file format even before we start implementing such configuration.
|
335
|
+
|
336
|
+
And you never know, maybe someone will love it so much he'll implement necessary Plugins so then others and you will be able to use *configlmm* to deploy such infrastructure.
|
337
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
require 'yard'
|
6
|
+
|
7
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
8
|
+
t.pattern = 'spec/**/*_spec.rb,Plugins/**/*_spec.rb'
|
9
|
+
end
|
10
|
+
|
11
|
+
YARD::Rake::YardocTask.new(:doc) do |t|
|
12
|
+
t.files = ['**/*.rb', '*.rb', '-', '*.md']
|
13
|
+
end
|
14
|
+
|
15
|
+
task default: :spec
|
data/UNLICENSE
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
This is free and unencumbered software released into the public domain.
|
2
|
+
|
3
|
+
Anyone is free to copy, modify, publish, use, compile, sell, or
|
4
|
+
distribute this software, either in source code form or as a compiled
|
5
|
+
binary, for any purpose, commercial or non-commercial, and by any
|
6
|
+
means.
|
7
|
+
|
8
|
+
In jurisdictions that recognize copyright laws, the author or authors
|
9
|
+
of this software dedicate any and all copyright interest in the
|
10
|
+
software to the public domain. We make this dedication for the benefit
|
11
|
+
of the public at large and to the detriment of our heirs and
|
12
|
+
successors. We intend this dedication to be an overt act of
|
13
|
+
relinquishment in perpetuity of all present and future rights to this
|
14
|
+
software under copyright law.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
19
|
+
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
20
|
+
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
21
|
+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
24
|
+
For more information, please refer to <http://unlicense.org/>
|
data/bin/configlmm
ADDED
data/bin/console
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'ConfigLMM'
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
require 'irb'
|
11
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
|
2
|
+
# frozen_string_literal: true
|
3
|
+
require_relative 'plugin'
|
4
|
+
|
5
|
+
module ConfigLMM
|
6
|
+
module Framework
|
7
|
+
|
8
|
+
class DNS < Framework::Plugin
|
9
|
+
DEFAULT_TTL = 600
|
10
|
+
|
11
|
+
def processDNS(domain, items)
|
12
|
+
records = {}
|
13
|
+
|
14
|
+
if items.is_a?(Hash)
|
15
|
+
# More complicated structure with Hash
|
16
|
+
# TODO Implement TTL
|
17
|
+
raise 'Hash object not implemented!'
|
18
|
+
end
|
19
|
+
|
20
|
+
if items.is_a?(String)
|
21
|
+
items = items.split(';')
|
22
|
+
end
|
23
|
+
|
24
|
+
items.each do |item|
|
25
|
+
type, content = item.strip.split('=')
|
26
|
+
content += '.' if type == 'CNAME' || type == 'ALIAS'
|
27
|
+
content = domain + '.' if content == '@' || content == '@.'
|
28
|
+
content = self.class.externalIp if content == '@me'
|
29
|
+
records[type] ||= []
|
30
|
+
records[type] << { type: type, content: content, ttl: DEFAULT_TTL }
|
31
|
+
end
|
32
|
+
|
33
|
+
records
|
34
|
+
end
|
35
|
+
|
36
|
+
def showManualDNSSteps(target, message)
|
37
|
+
if !target['DNS'].to_h.empty?
|
38
|
+
target['DNS'].each do |domain, data|
|
39
|
+
yield(domain)
|
40
|
+
prompt.say(message, :color => :magenta) if message
|
41
|
+
data.each do |name, data|
|
42
|
+
self.processDNS(domain, data).each do |type, records|
|
43
|
+
records.each do |record|
|
44
|
+
prompt.say(" * Type: #{record[:type]}\n Name: #{name}\n Content: #{record[:content]}", :color => :bold)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.externalIp
|
53
|
+
return @ExternalIp if @ExternalIp
|
54
|
+
@ExternalIp = HTTP.get('https://api.ipify.org').body.to_s
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.externalIp=(ip)
|
58
|
+
@ExternalIp = ip
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ConfigLMM
|
4
|
+
module Framework
|
5
|
+
PluginMissingError = Class.new(RuntimeError)
|
6
|
+
|
7
|
+
class PluginError < RuntimeError
|
8
|
+
def initialize(message, cause = nil)
|
9
|
+
super(message)
|
10
|
+
@cause = cause
|
11
|
+
end
|
12
|
+
|
13
|
+
def cause
|
14
|
+
@cause
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
PluginLoadError = Class.new(PluginError)
|
19
|
+
PluginProcessError = Class.new(PluginError)
|
20
|
+
PluginAuthError = Class.new(PluginError)
|
21
|
+
PluginPrerequisite = Class.new(PluginError)
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative 'plugin'
|
5
|
+
require_relative 'errors'
|
6
|
+
require_relative 'store'
|
7
|
+
require 'addressable/idna'
|
8
|
+
require 'http'
|
9
|
+
require 'fileutils'
|
10
|
+
|
11
|
+
module ConfigLMM
|
12
|
+
module Framework
|
13
|
+
|
14
|
+
class NginxApp < Framework::Plugin
|
15
|
+
|
16
|
+
def writeNginxConfig(dir, name, id, target, activeState, context, options)
|
17
|
+
outputFolder = options['output']
|
18
|
+
|
19
|
+
updateTargetConfig(target)
|
20
|
+
|
21
|
+
template = ERB.new(File.read(dir + '/' + name + '.conf.erb'))
|
22
|
+
renderTemplate(template, target, outputFolder + '/nginx/servers-lmm/' + name + '.conf', options)
|
23
|
+
plugins[:Nginx].actionNginxBuild(id, target, activeState, context, options)
|
24
|
+
end
|
25
|
+
|
26
|
+
def deployNginxConfig(id, target, activeState, context, options)
|
27
|
+
outputFolder = options['output']
|
28
|
+
|
29
|
+
if !target['Location'] || target['Location'] == '@me'
|
30
|
+
copy(outputFolder + '/nginx/servers-lmm', '/etc/nginx/', options['dry'])
|
31
|
+
end
|
32
|
+
|
33
|
+
plugins[:Nginx].actionNginxDeploy(id, target, activeState, context, options)
|
34
|
+
end
|
35
|
+
|
36
|
+
def cleanupNginxConfig(name, id, state, context, options)
|
37
|
+
rm('/etc/nginx/servers-lmm/' + name + '.conf', options['dry'])
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def updateTargetConfig(target)
|
43
|
+
target['TLS'] = true if target['TLS'].nil?
|
44
|
+
|
45
|
+
if !target['Port']
|
46
|
+
target['Port'] = target['TLS'] ? 443 : 80
|
47
|
+
end
|
48
|
+
if target['Domain']
|
49
|
+
target['Domain'] = Addressable::IDNA.to_ascii(target['Domain'])
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|