Comments (19)
All good ideas. I would also agree with @nehmebilal on doing small changes at a time, as it's easier to look at what's possible once we are closer to the goals.
In my opinion, the node type addition can already enable a lot. If we do that, I would still consider deprecating the DeploymentId name in favor of something like YamsClusterId, to disambiguate with whatever hosting technology Yams runs on. Node type on the other hand doesn't need a Yams prefix in it, as it is a logical name that only applies inside the (Yams) cluster, and it doesn't matter if other hosting technologies reuse the same name
from yams.
Here is what I am thinking to make it possible for users to add additional properties such as "NodeType" easily.
The DeploymentConfig.json will look as follows:
{
"Applications":
[
{
"Id": "app1",
"Version": "1.0.0",
"YamsClusters": [ "YAMS_CLUSTER_ID" ],
"Properties":
{
"NodeType": "PROD"
}
},
{
"Id": "app1",
"Version": "1.0.1",
"YamsClusters": [ "YAMS_CLUSTER_ID"],
"Properties":
{
"NodeType": "QA"
}
},
]
}
Yams will require an implementation of the following interface to match the deployments to clusters:
public interface IAppDeploymentMatcher
{
bool MatchesCurrentCluster(AppDeploymentConfig appDeploymentConfig);
}
The default implementation uses the Yams cluster id:
public class YamsClusterIdDeploymentMatcher : IAppDeploymentMatcher
{
private string _yamsClusterId;
public ClusterIdDeploymentMatcher(string yamsClusterId)
{
_yamsClusterId = yamsClusterId;
}
public bool MatchesCurrentCluster(AppDeploymentConfig appDeploymentConfig)
{
return appDeploymentConfig.YamsClusterId == _yamsClusterId;
}
}
To support NodeType, the user can supply a custom implementation as follows:
public class CustomAppDeploymentMatcher : IAppDeploymentMatcher
{
...
public bool MatchesCurrentCluster(AppDeploymentConfig appDeploymentConfig)
{
if(appDeploymentConfig.YamsClusterId != _yamsClusterId)
{
return false;
}
// Verify that the node type matches
string nodeType = "";
if(appDeploymentConfig.Properties.TryGetValue("NodeType", out nodeType))
{
return nodeType == _nodeType;
}
return false;
}
}
You could even write a matcher that matches on a start date for a scheduled job. Another example would be a matcher that makes a service call to fetch some configs and decide if the app should be deployed or not.
How does that sound?
from yams.
Just to list some of the issues discussed here:
- I would like to have a
NodeType
in myDeploymentConfig.json
so that I can separate my deployments per type into different clusters. This feature would also be useful for Orleans where backend and frontend apps are deployed to separate WorkerRole's. I personally think we should generalize this and make it possible to add any number of user meta-data to the DeploymentConfig.json. I have some ideas but I'll go in more details once we have a dedicated issue :) - I would like to have separate
DeploymentConfig.json
for unrelated apps. This is totally doable today. For the SQL scenario, you can pass to your host exe the key of the row where the correspondingDeploymentConfig.json
is stored. Then, pass this down to your implementation ofIDeploymentRepository
which will fetch the right data. It's also doable using the default blob storage solution by using separate storage accounts for unrelated apps. By the way, you can even store the json in different format and then populate theDeploymentConfig
class using theAddApplication
Apis.
I'm sure there's more between the lines :)
from yams.
Having a ClusterId and NodeTypeId, and no longer use DeploymentId, would by itself be a large enabler of other things. The SQL script I shared would become possible, for example.
The config representations can be done now, in one way or another, and one form can be easily mapped to another. So yeah, it's really that use of Cluster & NodeType abstractions that are the thing to focus on.
from yams.
@danvanderboom Please take a look at #34 and let us know if that works for you.
from yams.
Great work!
It might take me a week or two before I get a chance to test it out and upgrade our current project to use the newest version, but I'll report back when I do.
from yams.
There are several ideas here but I'm going to focus on the NodeType
proposal to keep the discussion focussed. If I understand correctly, @danvanderboom is proposing adding a NodeType
(let's call it that for now) field to the DeploymentConfig.json as follows:
{
"Applications":
[
{
"Id": "app1",
"Version": "1.0.0",
"DeploymentIds": [ "YAMS_CLUSTER_ID" ],
"NodeType": "PROD"
},
{
"Id": "app1",
"Version": "1.0.1",
"DeploymentIds": [ "YAMS_CLUSTER_ID"]
"NodeType": "QA"
},
]
}
The Yams host on each node will know its type and will pull the appropriate deployments based on their types as described in the json above.
The current solution is to concatenate PROD or QA to the DeploymentId (which should be renamed to YamsClusterId).
@danvanderboom Is that accurate?
from yams.
Here's how I see it looking, ideally, for a system with three node types in a QA cluster, and where each node type has two services configured to be installed.
{
"ClusterId": "MyProduct-QA",
"NodeTypes": [
{
"NodeTypeId": "Storage",
"Services": [
{
"Id": "StorageService",
"Version": "3.0.0.0",
"Executable": "<path to .exe>",
"ExecutableArgs": "<arguments with tokens for special values>",
"Properties": [
{ "ConfigFilesPackageUrl": "<URL to download config files package>" },
{ "AnotherCustomProperty": "..." }
]
},
{
"Id": "LoggingService",
"Version": "1.0.0.0",
"Executable": "<path to .exe>",
"ExecutableArgs": "<arguments with tokens for special values>"
}
],
"Properties": [
{ "SomeSpecialService": { "Id": "LoggingService", "Version": "1.0.0.0" } }
]
},
{
"NodeTypeId": "ComputeA",
"Services": [
{
"Id": "ComputeServiceA",
"Version": "3.0.0.0",
"Executable": "<path to .exe>",
"ExecutableArgs": "<arguments with tokens for special values>"
},
{
"Id": "LoggingService",
"Version": "1.0.0.0",
"Executable": "<path to .exe>",
"ExecutableArgs": "<arguments with tokens for special values>"
}
]
},
{
"NodeTypeId": "ComputeB",
"Services": [
{
"Id": "ComputeServiceB",
"Version": "1.0.0.0",
"Executable": "<path to .exe>",
"ExecutableArgs": "<arguments with tokens for special values>"
},
{
"Id": "LoggingService",
"Version": "1.0.0.0",
"Executable": "<path to .exe>",
"ExecutableArgs": "<arguments with tokens for special values>"
}
]
}
]
}
Then you'd keep separate configurations for the other environments. In my case where I'm storing these in SQL Server, each cluster's config/manifest is a separate row in a table.
from yams.
So when YAMS starts up, it would need to know two things:
- ClusterId
- NodeTypeId
from yams.
This is a cluster manifest. And we'd have separate manifests, one for each cluster/environment.
This can be used in a file based way, versioning with code, differentiating its details by solution configuration, and loading the .json file to configure YAMS... and it's also friendly for storing as rows in a database table in case you want centralized configuration.
from yams.
With a Properties dictionary at the Cluster level as well, these settings could be made available to YAMS extensions like deployment storage providers. This would centralize and make convenient configuration for any and all YAMS extensions, as well as any switches or settings that may alter the operation of YAMS (not sure if there are any of these).
from yams.
If we could call:
IDeploymentRepository.FetchNodeTypeConfig("MyProduct-QA", "ComputeA")
... we'd get back a NodeTypeConfig or NodeTypeManifest object, which would be one of these:
{
"NodeTypeId": "ComputeA",
"Services": [
{
"Id": "ComputeServiceA",
"Version": "3.0.0.0",
"Executable": "<path to .exe>",
"ExecutableArgs": "<arguments with tokens for special values>"
},
{
"Id": "LoggingService",
"Version": "1.0.0.0",
"Executable": "<path to .exe>",
"ExecutableArgs": "<arguments with tokens for special values>"
}
]
}
And to not be totally confusing, "Services" are normally called "Applications" in YAMS.
A call to:
IDeploymentRepository.FetchClusterConfig("MyProduct-QA")
... would give us the whole big cluster manifest JSON fragment I shared previously.
from yams.
A SQL Server database setup script for supporting this kind of model:
https://gist.github.com/danvanderboom/a584bbf2fbdb4a626bb72912bd4828f5
from yams.
Thanks for the ideas @danvanderboom. I doubt that we will make such major changes in one go. It would be great if we can focus on one issue at a time. You never know, It's possible that there are existing solutions to some of the challenges you're trying to address.
My suggestion would be to identify functionality that is not supported (or can be improved) and open a corresponding focused issue to discuss each. Baby steps :)
from yams.
I think that's reasonable. After this we can update the Cloud Services sample to use a node type that matches the worker role name (in addition to the deployment id) if it supports multiple node types.
I assume these values can also be used as tokens in the command line arguments when launching the external application?
from yams.
That will work for me, @nehmebilal. Thanks for taking the time to focus on this!
from yams.
@danvanderboom No problem :)
@jdom Good point. Yes, we should be able to make the properties available as tokens that can be used in the AppConfig.json.
from yams.
1.1.0-rc is up!
from yams.
Closing.. Feel free to re-open if you find any issues.
from yams.
Related Issues (20)
- Compress application binaries HOT 10
- Monitor Application health HOT 17
- This repo is missing important files HOT 1
- DI make CloudBlobClient a singleton HOT 1
- Nuget package target framework HOT 19
- Support prerelease versions like in SemVer HOT 9
- Make DeploymentConfig serializable to JSON HOT 6
- System.IO.IOException: There is not enough space on the disk. HOT 7
- Yams studio can not be running because of the Newtonsoft.Json version binding setting in App.config HOT 5
- Tutorial for on premise needs the cloud? HOT 5
- Consider creating separate Host and Client NuGet packages HOT 6
- Support for load balancing HOT 1
- REST API HOT 5
- Yams Client - confusion with arguments HOT 4
- Yams crashes with broken pipe HOT 2
- Add package version to assembly info HOT 2
- Minimize network traffic during app deployment HOT 1
- Extend client logs with app identity HOT 3
- Use XUnit for testing HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from yams.