Gitops / IaC with multiple environments - devops

We provide online services for multiple customers. Each customers has given urls, eg.
customer1-preprod.service.company.com
customer1-int.service.company.com
customer1-prod.service.company.com
...
Currently we have good old bash scripts to manage the deployment, create new customers etc... And this is really hard to manage.
As a developer, I like the gitops approach, I find it nice to describe & commit how an application should be deployed. However in our case we should have dedicated directory, in the git repository, for each customer, which will make it hard to maintain:
/gitops
/customer1
/preprod
a-deploy-descriptor.xml
/prod
..
Then in order to update a client, we would have to copy-paste updates from file to file. The same to create new customers. It doesn't look very easy.
Are there ways / tools to apply infrastructure as code, but for unlimited number of environments?
(I am new to devops, sorry if this is not clear)

Related

App for managing apps (architecture)

I know it's gonna be a very broad question and I'm pretty sure this is not anything new in todays world, but I really don't now where to start on this one.
I've started working on a rails-based service that would allow users to create, configure and manage their projects (basicaly copies of a single app with customization). The projects would be run on a subdomain with an option of connecting their own domain. (Quite similar to how SquareSpace and Wix and many other website building services handle their websites)
I want these projects to be as flexible and customizable as possible (including the visual design, some additional features etc) while maintaing ease of setup and updates for the codebase itself.
So the questions I start with:
Should each project be a separate app (basicaly a copy out of the
same repo) with its own configs, database, nginx and unicorn
configs, etc. or should I keep all in 1 app and differenciate them
with different configs and maybe databases and assets?
If it's better to keep everything separated...
... what's the best setup process (provided that I have basic configuration to start with)?
... how would I be able to update them all (with bugfixes, new features, performance improvements etc.) from one place?
If I keep all the projects in the same app...
... how should I manage the configuration concurency between projects?
... how do I separate the data and assets?
As always, I'd be grateful for any sufficient help I can get.
I have no experience building these kind of things and maybe there is an easy solution I'm not aware of. But my answer may give you some ideas/pointers to start with.
1) It's hard to give an accurate answer but based on the high personalization criteria and the "copies of a single app" you talk about, I would go for an architecture more PAAS-like than SAAS-like. So separated apps.
2.1) You may want to consider a setting using:
A main rails app, with a main webserver and a main nginx conf. A wildcard domain.
A bunch of dynamically managed docker containers. Each container is initialized from your single app, and then personalized by the user. User is associated to its containers through the main rails app. When a container is created from the main app, the main nginx config is updated (i.e. by adding a file in sites-enabled which define a new 'server' that bind the open port of the new container, and the right 'server_name').
Each contained rails app ship an unique and shared rails engine. The rails engine is shipped by adding the corresponding gem in the Gemfile so it can be updated.
2.2) You update the 'shared rails engine' gem. You can then run bundle install in each containers.
People interested in these kind of setups may consider tools like dokku and deis.
Consider a multi-tenant architecture. We've used it effectively for fleet-genius.com.
The following link provides a good overview of the architecture from a Rails point of view.
http://blog.elbowroomstudios.com/zero-to-multitenant-in-15-minutes-a-rails-walkthrough/

Git - Heroku deploy app that is composed of a couple of git repos

Recently I built an rails app for a local business. They like this app so much that they've gotten a couple of other local businesses interested in having their own version of the app.
Here lies the problem that Im uncertain how to fix. The core business logic behind the app would be the same for these new and future customers(about 80% of the code). Whereas each customer would have their own static pages, as well as their own stylesheets.
Ive thought about multi-tenancy, but these guys are picky enough that it honestly seems easier to build the app function the way they want, as opposed to building around DB stored customer preferences(perhaps I'm wrong here).
I would like configure this application so that I can push changes to the core business logic without overwriting the customer specific portions of the site. Perhaps creating a second repo which only contains the customer specific content.
How do I configure this app/Git repo so that I can personalize the app without creating a bunch of parallel repos?
As Meagar pointed out the solution to this scenario is to encapsulate the core business logic of these applications into a Gem that can be reused later down the road.

How to extend an existing Ruby on Rails CMS to host multiple sites?

I am trying to build a CMS I can use to host multiple sites. I know I'm going to end up reinventing the wheel a million times with this project, so I'm thinking about extending an existing open source Ruby on Rails CMS to meet my needs.
One of those needs is to be able to run multiple sites, while using only one code-base. That way, when there's an update I want to make, I can update it in one place, and the change is reflected on all of the sites. I think that this will be able to scale by running multiple instances of the application.
I think that I can use the domain/subdomain to determine which data to display. For example, someone goes to subdomain1.mysite.com and the application looks in the database for the content for subdomain1.
The problem I see is with most pre-built CMS solutions, they are only designed to host one site, including the one I want to use. So the database is structured to work with one site. However, I had the idea that I could overcome this by "creating a new database" for each site, then specifying which database to connect to based on the domain/subdomain as I mentioned above.
I'm thinking of hosting this on Heroku, so I'm wondering what my options for this might be. I'm not very familiar with Amazon S3, or Amazon SimpleDB, but I feel like there's some sort of "cloud database" that would make this solution a lot more realistic, than creating a new MySQL database for each site.
What do you think? Am I thinking about this the wrong way? What advice do you have to offer in this area?
I've worked on a Rails app like this, and the way it was done there was named-based virtual hosts, with db entries for each site running. Each record was scoped to a site if necessary (blog posts, etc.) while users would have access to all sites running out of that db. Administrator permissions could be global or scoped to one or more sites.
You're absolutely correct when you say you'll reinvent the wheel a million times during the project. Plugins will likely require hacking on top of the CMS itself.
In my situation, it ended up being a waste of almost a million dollars of company money to build that codebase to run multiple sites while still being able to cater to the whims of each client site. It worked, but was not very maintainable due to the number of site-specific hacks that subsequently entered the codebase. You may be able to make it work if you don't have to worry about catering to specific client sites running on your platform.
In the end, you're going to need a layer of indirection to handle the different sites regardless of methodology. We ended up putting it in the database itself. If you go with the different-db-for-each-site method you mentioned, you'll put that layer in your code instead. I'm not sure which one is the better method.
I hope you're able to pull this off. I failed.
Also, as I learned today, Heroku offers postgres instead of mysql for rails apps.
There's James Stewart's Theme Support Plugin for Rails 2.3, and lucasefe's themes_for_rails gem for Rails 3+.
I just started using the 2.3 version and it's working well so far.

Which is better: Use the multi-tenant plugin or different environments?

Which solution is easier to maintain: The Multi-Tenant Plugin (http://www.grails.org/plugin/multi-tenant), or creating a different environment (http://grails.org/doc/latest/guide/3.%20Configuration.html#3.2%20Environments) for each instance of an application which is essentially the same (with minor changes) for each company?
The answer depends on how your application runs, and how you plan to deploy it. If you can deploy multiple WAR files, one for each client, then using environments is a possible option. However, I would strongly urge you to "white label" your application manually, or use the multi-tenant plugin, as environments will get unwieldy quickly and does not support adding custom views/logic per customer, which invariably becomes a requirement.

How to reuse a rails app

I developed a rails app for a school alumni site.
Now another school wants me to develop a similar site for them.
I want to reuse the app. Data structure will be same but the actual data will be different. Design layout will be similar but design itself will be different.
One option is that I just copy the app and modify it. But in this case, I need to manage 2 apps as they evolve.
Another option will be to make the app generalized and customizable (Database will be separated though). Views will have a lot of a lot of branches.
I could use on database for multiple apps but I am sure it will require a lot of jobs.
Another option will be to move controllers and models to plugins so that 2 apps share them.
Do you have any experience with such a case? If so, can you share it with me?
Thanks.
Sam
This might be a little unorthodox, but if you're using git, you can create two branches
one for the school alumni site
one for the similar site
The root code will stay in the master branch. Your development flow would then be:
branch off the master
make edits
pull edits into master when satisfied
pull the master changes into the branches.
You can continue to locally modify the branches as needed, but you will need to be careful about introducing conflicting edits between master/branch.
If there is any way to avoid the complexity of forking your code into two separate applications you should do it.
Making the application generalized and customizable as you are suggesting moves your one off consulting project into something closer to a standalone product (which might be more profitable).
You'd be surprised how far you can get with different stylesheets, layouts and judicious use of localisation.
2 apps will share:
Models
Helpers
Controllers
They won't share:
Views
I am not sure about database yet.
I may separate views using skin concept like:
app/views/app1/...
app/views/app2/...
I am still thinking about database.
I'm using git submodules and symlinks. There's a submodule to the shared project in Rails.root/shared. Then there's symlinks from app/models to shared/app/models, and so on.

Resources