Deploy a Multi-Tenant WebApi with Tenant-Specific Configuration - octopus-deploy

Is there a way to deploy a single instance multi-tenant aware web api with specific configuration per tenant?
We have an Asp.net Web Api witch identify the tenant by claims inside a JWT but into the web.config are configuration per tenant. Example
<configuration>
<appSettings>
...
</appSettings>
<tenants>
<tenant key="1">
<add key="key1" value="false" />
</tenant>
<tenant key="2">
<add key="key1" value="value2" />
</tenant>
</tenants>
</configuration>
We dont use multi-tenancy in Octopus becose is only one installation per target but we cant imagine how to store and insert the configuration per tenant.
Any Ideas?

Full disclosure: I work for Octopus Deploy.
If I understand correctly you have a single binary that serves multiple tenants and web.config is used to specify which tenants are served by the application.
If so, then I would recommend splitting your application into 2 Octopus Projects. One which represents application code and one which represents configuration. The configuration Project would use multi tenancy in Octopus to add relevant entries to the web.config for each deployed tenant. This can be done using a config transformation or a custom script.
SO is a public forum so if you would like to share some sensitive information about your project then I would recommend you reach out to us via https://octopus.com/support.
Regards,

Related

Don't want to store properties in database

I have some properties in my microservice. They are changed a lot so I want to store them somewhere out of microservice so that I don't have to undeploy it again and again. One solution is to store them in database but it will be less efficient that way. Can you advise me a solution where I can store them?
Basically this microservice is used by a vast number of people. I want that file to be read ONCE when microservice is deployed (unless or until there is some change in the file) to minimize the calls.
You should use Spring Cloud Config which enables to use a centralized server which exposes a Git Repo which you can use to store environment specific configuration files (application.properties)
You should go with Centralized configuration, spring cloud supports config server, It is highly recommended for microservice architecture.
For reference: https://spring.io/guides/gs/centralized-configuration/
Basically, you have a centralized place to store all the configurations and don't need the redeploy the application every time you change the configs.
NOTE: in case you change the db properties then probably you need the restart the service

Spring Boot: Handle configuration in multitenant application

I am implementing a Spring Boot application which will be providing a multitenant environment. That is achieved in my case by using a database schema for each customer. Example see this project.
Now I am wondering how to implement tenant-specific configurations. I am using #ConfigurationProperties to bundle my property values, but these are getting instantiated once and not for each tenant.
What if I would like to use Spring Cloud Config with multiple tenant specific git repository as an configuration backend. Would it be possible when using a jdbc backend for Spring Cloud Config?
Is there any way with default Spring mechanisms or do I have to implement a database based configuration framework myself?
Edit: For example I have two tenants called Tenant1 and Tenant2. Both are running over the same application in the same context and are writing in the database schemes tenant_1 and tenant_2.
Identification of tenants is happening over keycloak (see Spring Keycloak multi tenant example). So I identify the tenantId from the jwt token and select the database connection like described here.
But now I would need the same mechanism for #Configuration beans. Since #Configuration beans are as far as I know Singletons, so there is always ONE configuration per application scope, and not ONE configuration per tenant.
So using Spring Cloud Config Tenant1 is using https://git-url/tenant1, Tenant2 is using Hashicorp Vault as backend and perhaps Tenant3 will be using a jdbc based configuration backend. And all of that in ONE (of course scalable) application.
In case your application uses tenant specific files (html templates etc), the following can be applied. As I have used the below approach for handling many tenants and works fine and easy to maintain.
I would suggest that you maintain a consistent configuration source (JDBC) for all of your tenant configurations. This helps you have a single source that is cacheable and scalable for your application. Also, you could have your tenants navigate to a configuration page to manage their settings and alter them to suit their needs at any point of time on the fly. (Example Settings: Records Per Page, Theme, Logo, Filters etc...)
Having the tenant configuration in files in git will be a difficult task when you wanted to auto-provision tenant's when they sign-up as it will involve couple of distributed services. Having them in a TenantSettings table with the tenantId as a column could help you get the data in no time and will be easy.
You can use Spring Cloud Config for your scenario and it is adoptable. It is easily configurable and provides out of the box features. For your specific scenario, you can have any number of microservices running yet all controlled by one Spring Cloud Config Server which is connected to one Git Repository. Your all microservices are asking configuration properties from Spring Cloud Config Server and it is directly fetching properties from Git Repository. That repository can have multiple property files. It can hold common properties for all the microservices or specific service based configuration properties. If you want to keep confidential properties more securely, that is also made possible via HashiCorp vault. I will leave an image below for you to get a better idea about this concept.
In the below image, you can see the Git Repository with common configuration property files and specific configuration property files for different services yet in same repository.
I will add another image for you to get a better idea how does this can be arranged with application profiles as well.
Finally I will add something additional to show the power of Spring Cloud Config and out of the box features it allows us to play with. You can automatically refresh configuration properties in running application as well. You can configure Spring Cloud Config to do that. I will add an architectural diagram to achieve that.
References for this answer is taken from Spring in Action, Fifth Edition
Craig Walls

Spring integration server URL configuration approach

I am using spring integration for my framework. The framework will be used by many projects. Currently, i checked that the example in Spring integration. The URL for http-outbound is hardcode in the xml.
As the framework will be used by many people with different URL. What's the approach to let the end user project to configure the url? I was using maven build with parameter. I found that it is not that easy to maintain if i have too many parameter to configure. Is there any better way to do so? What's the common practice in the industry? Thanks.
<int-http:outbound-channel-adapter id="example"
url="http://localhost/example"
http-method="GET"
channel="requests"
charset="UTF-8"
extract-payload="false"
expected-response-type="java.lang.String"
request-factory="someRequestFactory"
order="3"
auto-startup="false"/>
Take a look, please, to the standard Spring Framework feature - Property Placeholder.
So, that url can be configured like:
url="${service.url}"
And each application would be able to provide their own value (target URL) via external properties file or any other possible source for PropertyPlaceholderConfigurer.

Startup.cs not needed on DEV machine but needed for deployment

I am developing an ASP.NET Web API v2 application. My application works fine from my DEV machine but when I go to deploy it to my server it gives the following errors.
The following errors occurred while attempting to load the app.
- No assembly found containing an OwinStartupAttribute.
- No assembly found containing a Startup or [AssemblyName].Startup class.
To disable OWIN startup discovery, add the appSetting owin:AutomaticAppStartup with a value of "false" in your web.config.
To specify the OWIN startup Assembly, Class, or Method, add the appSetting owin:AppStartup with the fully qualified startup class or configuration method name in your web.config.
After searching Google, SO, and other sites I found adding a default Startup.cs class to my project fixed the issue. The problem is I don't know how.
What did adding Startup.cs do?
Why would my app compile and run on my development machine without Startup.cs?
This seems to involve OWIN but I was not even aware I was making use of any OWIN features.
This is most likely due to the way OWIN searches for its entry point (Startup class). In your dev environment you probably have a DLL in the project folder that has an OWIN Startup class. That dll is not being deployed as part of the deployment step and therefore doesn't exist in your deployed location.
Another posibility, along the same lines, is you're using .config transformations and you have defined a Startup class in your DEV config but not in your deployed config.
<appSettings>
<add key="owin:appStartup" value="StartupDemo.ProductionStartup" />
</appSettings>
OWIN Startup Class Detection might be informative.
MVC5 uses OWIN pipeline by default so it's "under the hood". Perhaps you migrated from a previous MVC site and that's why the Startup class was missing?
Cheers!

ASP.NET MVC3 Multiple Databases

Hello all:
I'm building an app using C#/MVC3/Razor which has a database configured in web.config. One of the requirements is to push the data to another database. is this doable within the MVC3 framework or should i just connect to the second database using standard methods/sql/?
thanks
You could have a second connection string in your web.config and configure your ORM framework or whatever you are using to access those databases to use this second connection string:
<connectionStrings>
<add name="db1" connectionString="Data Source=serverName;Initial Catalog=dbName1;User Id=foo;Password=secret;" providerName="System.Data.SqlClient" />
<add name="db2" connectionString="Data Source=otherServerName;Initial Catalog=dbName2;User Id=bar;Password=secret;" providerName="System.Data.SqlClient" />
</connectionStrings>
Just one thing to remember: the ADO.NET Connection Pool is per App Domain and per connection string meaning that two separate connection pools will be held in this case.
<connectionStrings>
<add name="First_DB_Conn" connectionString="" providerName="Some_Provider" />
<add name="Second_DB_Conn" connectionString="" providerName="Some_Provider" />
</connectionStrings>
This way you can add more connection to another dbs
ASP.NET MVC itself contains nothing about databases (or any form of underlying persistence layer). In the MVC3 tools update some tooling for developers does make direct use of Entity Framework 4.1's "code first" capabilities.
But this is can be customised (eg. your own T4 templates or different scaffolding or completely ignored (manually write all persistence logic). The latter would be needed if your application doesn't map to CRUD operations that the scaffolding assumes.
Doing it yourself could use multiple ADO.NET connections (with multiple connections strings in the .config file) or multiple ORM models for different databases.

Resources