Sharing resources in Pulumi with Azure:Native - c#

I'm currently in the process of migrating all of our infrastructure to Pulumi and I'm slightly confused by how to organise some of my resources.
My company has decided that we want to group our projects by product names, so my current structure is something like this:
Infrastructure
-Product1
--MyCode.cs
--Pulumi.yaml
--Pulumi.dev.yaml
--Pulumi.prod.yaml
-Product2
--MyCode.cs
--Pulumi.yaml
--Pulumi.dev.yaml
Products generally have a single Vnet. So lets say Product1 has a vnet named PRODUCT1-VNET, this is used by both the Prod and Dev stacks which create their own subnets that attach to it. If i put this inside MyCode.cs and run both stacks, it will obviously create two Vnets, so I need a way to create a single vnet and have both stacks use it.
Should I create a seperate project for shared resources something like:
Infrastructure
|-Product1
|--MyCode.cs
|--Pulumi.yaml
|--Pulumi.dev.yaml
|--Pulumi.prod.yaml
|--|Product1-Shared
| |--MySharedResources.cs
| |--Pulumi.yaml
| |--Pulumi.dev.yaml
| |--Pulumi.prod.yaml
|-Product2
|--MyCode.cs
|--Pulumi.yaml
|--Pulumi.dev.yaml
And then use StackReference to get the outputs from MySharedResource.cs
Or is there a better way? It feels like doing this will cause some serious project bloat over time, i,e If I have 10 products will result in me having 20 projects which could get out of control management wise?
I've read through https://www.pulumi.com/docs/guides/organizing-projects-stacks/ but this uses a different structure in that it groups by resource type and not products and has no nested projects, so I'm unsure if deep nesting projects is the correct solution

Related

multi tenant or multi instance application on intranet

I have an existing MVC app which will be utlized by another user group in the near future. Both the existing and new user group/program will have independant data. I was just thinking to add flags in the tables to distinguish between the two user group/programs and do some routing when they access the application to pull up respective data.
Now when it comes to code customization, for instance one group/program wants to have extra fields on a page which the first group does not want or the process flow of the application is seperate between the two user groups.
If the above two scenarios will occur frequently, should I just do a new web and database instance rather than customizing the code for each program/user group. This way both of my customers/user groups will have flexibility to add different logic/fields to the application.
The only con I see with the non-multi tenant approach is the time effort by the developer to maintain two seperate applications. I am scared of adding contional logic to customize the same code base for each different user group/program. Cost of infrastructure is not an issue. Also I do not forsee this application to be used by more than 2 user groups/programs at any time. So what do you guys think which apporach i should take and why? thanks all in advance
P.S The users arent any ninjas who will try to hack the site to see the other tenants data. They are corporate users. Theyd rather not use this application but its part of the process so they have to use it.
It's worth taking a look at microsoft's article on multi-tenancy.
I'm also working on trying to design an mvc app with such an architecture where each client can have separate fields and customised screens.
The conclusion that I have come to is that using an IOC container with multi-tenancy support will probably make the whole thing a lot easier.
Autofac has built in multi-tenancy support.
In terms of having logic for clients in each view I believe that if you go down the IOC path you can have a controller for each tenant and in that case hard coding such client specific logic isn't necessarily as bad as it would be having it hard coded all into a shared controller. In essence I believe when writing a component that is for a particular tenant you can switch you mindset to writing as if that tenant was the only one using the system.
The other solution I have landed in for customising views is to use a variation of the RazorGenerator approach for compiled views where I have each tenants views compiled into a separate assembly and have created my own view engine (based on this) where I can swap out the assembly that I look for views in depending on a value in the routing parameters.
Of course I'm still exploring this approach and haven't fully flushed it out in order to find out where it may fall short.
If the difference in the 2 users' requirements is more than 10% of the screens/functionality then you better have 2 databases and apps. If it is expected to be less than 10% then just write separate actions (possibly with different prefixes or suffixes in Action names) for where the functionality differs.

How to turn on/off code modules?

I am trying to run multiple sites using single code base and code base consist of the following module (i.e. classes)
User module
Q & A module
Faq module
and each class works on MVC pattern i.e. it consist of
Entity class
Helper class (i.e. static class)
View (i.e. pages and controls)
and let say I have 2 sites site1.com and site2.com. And I am trying to achieve following functionality
site1.com can have User, Q & A and Faq module up and running
site2.com can have User and Q & A module live while Faq module is switched off but it can be turned-on if needed, so my query here is what is the best way to achieve such functionality
do I introduce a flag bit that I check on every page and control belonging to that module? It's more like CMS where you can turn on/off different features. I am trying to get my head around it, please provide me with an example or point out if I am taking the wrong approach.
You might want to look at Portable areas. You could design the code base so that each module is an area and then deploy them into the sites were they are needed.
After looking to some example and an extensive research I come to a conclusion that it depends upon 2 scenarios:
Scenario 1:
If in a case where there is only ten possible modules which are written once and require the whole update of the entire application if they need to be updated, then you can easily use checks which will propagate through the models and be used by the views to adjust the user interface (for example by showing or not the appropriate links in the web application menu).
Scenario 2:
If, instead, there is a case of many modules developed by many developers and it is unacceptable to require the update of the whole web application in order to update any of such modules, then look for plugins model, like for example the one used in FogBugz.
For making choice, consider following elements sorted by importance:
Maintainability: is it acceptable to modify the common code of the web application in order to change any of the modules?
Dependencies: are some modules dependent of others?
Performance: since we don't know the exact context, it's difficult to try to predict the impact of each solution. Maybe there will be
none, if you use heavy, cleverly designed caching.
Overall architecture: if there are reasons to do something monolithic (because of the interdependencies), the first solution
seems more appropriate; this is not the case if every module is
strictly separated from others.

Where to put shared parts when using the onion architecture?

I am trying to apply the onion architecture by J. Palermo, but I have a few things I am struggling with.
I have a few parts and I don't know exactly where to put these.
I have a plugin engine which reads a directory and determine what things to load en to do
Have some resource files with translations which are used in several projects. Where should I put these files?
I have some attributes which are used throughout the system. Where to put these?
I also have two 'base' controllers, some default results and views. Where should I put these?
All those items are used in several projects so I want to put the items at a central point.
My current solution structure looke like this:
Project.Core (contains the domain objects and interfaces of the repositories)
Project.Infrastructure (is the implementation of the core)
I am using MVC2.
I don't think it's something that the Onion architecture would solve by itself.
What I would do, is to put all these items in one or several projects, within another solution and build Nuget packages allowing me to deploy them everywhere I would need them.
This way I would have deployed items like your base controllers in your MVC project and plugin/translation stuff in your Infrastructure project.
That way, whenever you'll need to have those elements available in your newly created projects, you'll just have to deploy the package again.
Those items will become independent, stored in a central point (a new sln) and will have it's own release cycle!

How to solve the performance/memory issues related with having entities that depend on other entities in DDD?

Assuming that I'm using no ORM, and following DDD, consider the following case:
A Project has a set of Files.
I've created both a Project and a ProjectRepository and a File and a FileRepository classes.
My original idea was having all the File entities for a given Project being passed to it in its constructor. This Project instance would, of course, be created through the ProjectRepository.
The problem is that if I have a million files (and although I won't have a million files, I'll have enough ones to make this take a while), I'll have to load them all, even when I don't really need them.
What's the standard approach to this? I can't think of anything better than to pass a FileRepository to each Project instance.
Since you mention DDD: if there are two repositories it indicates that there are two Aggregate Roots. The whole point of the Aggregate Root concept is that each root is responsible for its entire object graph.
If you try to mix Files into a Project object graph, then the ownership of the Files is ambiguous. In other words, don't do this:
project
- file
- file
- file
Either treat them as two (associated) object graphs, or remodel the API so that there's only a single Aggregate Root (repository).
There is no standard way. This is domain driven design, so it depends on the domain, if you ask me.
Maybe you could add some more domain to your design.
You only have two concepts: a Project and a File. But you say you don't want to load the file (assuming that File will always load the content of the file).
So maybe you should think about a FileReference, which is a lightweight representation of a file (Name, Path, Size?).
For me it sounds like your problem is the handling of a large set of files and not OOP.
You could implement a service layer which your clients interact with which co-ordinates the repositories and returns the domain entities. This would provide a better separation of concerns; I personally don't think that your client should have access to your repositories.

How to make one ASP.NET MVC site "derive" from another

My question is similar to "ASP.NET 2 projects to share same files", but with an ASP.NET MVC slant.
Basically, we have two sites, one being based mostly on the other (roughly 90% views, controllers, images, in the second are identical to the first). However, in some cases, the views may be different, or a controller in the second site may be different to the first.
Are there any simple ways of achieving this in ASP.NET MVC?
So far, we've looked at using linked files to have two totally seperate projects where the second project shares the files it needs from the first.
One problem with this approach is that most pages in the second project don't literally exist in the virtual directory, it makes debugging a pain - you have to publish in order to generate the files so you can debug.
Does anyone have any better approaches, or ways this approach can be simplified?
This article might help: http://dotnetslackers.com/articles/aspnet/storing-asp-net-mvc-controllers-views-in-separate-assemblies.aspx
Essentially, it involves creating your own WebFormViewEngine which tells MVC where to look for the Views.
If they are 90% the same and you want to keep them in sync as functionality evolves I would consider making them into a single web application and using the host header to differentiate and to change the images/links/text/functionality/etc. between the two sites.
You can do this in your BaseController: look at the host header and create a Brand object that every page and view has access to, just like it might have aUser object. That Brand object can include the name of the site, the canonical Url for the site, the location of the image directory for that brand, boolean values to turn certain features on or off, ...
Now in a Controller you can just ask if (Brand.SupportsPageX) {...} to decide what to show next. And if you make the brand object part of your base view model or put it in the view collection you can have views that use the brand's name, image directory, ... to customize how they look.
Put as much as possible into a shared non-UI library project. I do that on every project that I work on this, increased testability, shared code with Windows Services, and a host of other reasons.
I've found that if you're aggressive with this then quite often over two-thirds of the project would be in the non-UI shared library.
After doing this, you can take things a step further and create a second library with some shared MVC/UI elements.
Depending on your opinion of it, RenderAction may help a bit here. As you know, RenderAction will allow you to group up those controller/view components and pass in variable arguments at runtime.
A project I'm working on currently has a similar requirement and we have started looking at using portable areas. I personally haven't delved very deeply into them at the moment, but it may be worth you taking a look.
I've been working with areas to create multiple websites that I can host with one hosting account. I would think you could use a similar approach. By implementing the common functionality in the base project, it will be available to each area. You can also override any of the base views or controllers by implementing them in the area. It may require some tweaking of the ViewEngine and Routing but I think it could be done.

Categories