1

I'm trying to create a startup script or task that changes the configuration settings in the cscfg file, that executes on role start.

I'm able to access these settings, but haven't been able to successfully change them. I'm hoping for pointers on how to change settings on Role Start, or if it's even possible.

Thanks.

EDIT: What I'm trying to accomplish

I'm trying to make a service to more easily configure configuration values on Azure applications. Right now, if I want to change a setting that it the same over 7 different environments, I have to change it in 7 different .cscfg files.

My thought is I can create a webservice, that the application will query for its configuration values. The webservice will look in a storage place, like Azure Tables, and return the correct configuration values. This way, I can edit just one value in Tables, and it will be changed in the correct environments much more quickly.

I've been able to integrate this into a deployment script pretty easily (package the app, get the settings, change the cscfg file, deploy). The problem with that is every time you want to change a setting, you have to redeploy.

Blake-o
  • 15
  • 2
  • 8
  • 5
    With this operation, what are you trying to accomplish? there may be a better way. Part of the challenge you have here is that if you have 10 instances, they're all going to try and do this. So we need to be careful about "global" startup operations and there's usually better ways to meet your needs. – BrentDaCodeMonkey Jul 15 '13 at 19:48
  • instead - try using build configuration specific cscfg files: ..DEV.cscfg, ..TEST.cscfg - and deploy them. – viperguynaz Jul 16 '13 at 01:06
  • Put a little backstory in about what I'm trying to accomplish. I have separate environment configuration settings like you said. With some projects, there are 30+ cscfg files - for different instances, versions, etc. – Blake-o Jul 16 '13 at 13:59

2 Answers2

1

Black-o, given that your desire appears to be to manage the connection settings among multiple deployments (30+), I would suggestion that perhaps your need would be better met by using a separate configuration store. This could be Azure Storage (tables, or perhaps just a config file in a blob container), a relational database, or perhaps even an external configuration service.

These options require only a minimum amount of information to be placed into the cscfg file (just enough to point at and authorize against the configuration store), and allow you to maintain all the detail settings side by side.

A simple example might use a single storage account, put the configuration settings into Azure Tables, and use a "deployment" ID as the partition key. The config file for deployment then just needs the connection info for the storage location (unless you want to get by with a shared access signature), and its deployment ID. Then can then retrieve the configuration settings on role startup and cache them locally for performance improvements (either in a distributed memory cache or perhaps on the temp "local storage" drive for each instance).

The code to pull all this together shouldn't take more then a couple hours. Just make sure you also account for resiliency in case your chosen configuration provider isn't available.

BrentDaCodeMonkey
  • 5,493
  • 20
  • 18
  • That's what I'm trying to do, I just have the webservice in between to get the settings from storage, and return them to the application. The problem i'm having is how to do that on role start (get the settings, set them, keep the role from restarting). For now, since I haven't got the tables storage set up yet, I just have the webservice returning a static value. That shouldn't affect anything on the application side though, it's getting the exact same thing it would from the service if it was using Tables. – Blake-o Jul 16 '13 at 20:34
  • According to your original post, you're trying to change the cloud service configuration settings. What I'm proposing is that instead of doing that, you set up your own store and thus don't need to update the cscfg any longer. Just pull the settings from your own store. – BrentDaCodeMonkey Jul 17 '13 at 15:32
  • Yes that's what I mean, maybe I was just unclear. I did say change, but I meant change the values the application is using. This doesn't necessarily mean change the value in the cscfg, just the value in the storage. Changing it in storage would change which value the application is using. In the cscfg, the only setting I would need outside of the defaults is the connection string to the storage. I wouldn't need to update/change the cscfg file at all. – Blake-o Jul 17 '13 at 20:12
  • The problems I'm having are connecting to the webservice and getting the values for the application, on role start. I can retrieve the values fine, but I can't figure out how to actually use them, or make the application use the values as settings. Also, I have to get around the default behavior of role recycling when a new configuration setting is retrieved, or else it will infinitely restart (start role, run role start script, get settings, restart because new settings were retrieved) – Blake-o Jul 17 '13 at 20:14
  • On role start, call your configuration service and pull all settings as one package/payload. Take the values returned from there, and place then into local storage (the temp storage location that's collocated with your role instance). This gives you a local, low latency storage option that's quasi-persistent. Next set a task that fires off periodically to query the configuration service for changes. The simplest way IMHO is to use a hash to quickly see if there is a version change in the payload. – BrentDaCodeMonkey Jul 18 '13 at 14:59
  • As for the role recycling when the cloud service's cscfg values are changed, that can be managed by adding/modifying the RoleEnvironmentStatusCheck value in the RoleEntryPoint derived class of your role. For more on the RoleEntryPoint methods, I'd recommend you give my blog post on the subject a quick read. http://brentdacodemonkey.wordpress.com/2011/09/24/leveraging-the-roleentrypoint-year-of-azure-week-12/ – BrentDaCodeMonkey Jul 18 '13 at 15:01
  • I've tried a little bit of playing with the RoleEnvironment, but I haven't got it to work. This is what I did - In the Onstart of webrole.cs - `RoleEnvironment.Changing += RoleEnvironment_Changing;` Below that - `void RoleEnvironment_Changing(object sender, RoleEnvironmentChangingEventArgs e) { if (e.Changes.Any(change => change is RoleEnvironmentConfigurationSettingChange)) { e.Cancel = false; } }` Then, I changed a setting in the portal, and it still transitioned. – Blake-o Jul 19 '13 at 15:32
  • As far as using the settings, I haven't had much success either. After I get the settings from the webservice, I can't figure out how to tell the role to actually use them. Also, how do I save them in local storage? – Blake-o Jul 19 '13 at 15:35
  • About recycling/transitioning - are they the same thing? When I change the setting in the portal, and it says instance is transitioning, is that the same as recycling? – Blake-o Jul 19 '13 at 16:12
  • I *think* transitioning it about moving the role instance to new hardware, perhaps an OS upgrade. I'm not 100% certain. As for the configuration settings, you'll create your own configuration provider, not use the cloud service configuration fetch. You *could* use the SetConfigurationPublisher to override the default, but honestly its just as easy to build your own configuration "provider" class and have all config requests leverage that. – BrentDaCodeMonkey Jul 19 '13 at 21:49
0

The only way to change the settings during runtime is via Management API - craft the new settings and execute "Update Deployment" operation. This will be rather slow because it honors update domains. So depending on your actual problem there might be a much better way to solve it.

sharptooth
  • 167,383
  • 100
  • 513
  • 979