Accessing Azure ServiceConfiguration settings in Node.js - node.js

I'm coming to the beta deployment phase of building a Node.js application running through iisnode on Windows Azure. Having set up multiple instances, as well as production/staging separation, my research has led me to the following conclusion:
If I want to change configuration settings on the fly without redeploying code, I need to use Service Configuration .cscfg files.
My problem is that I've stored various configuration settings in the <appSettings> and <iisnode> elements of web.config that I might want to change, which are currently exposed in my Node application via the process global object.
I've looked around MSDN, Node documentation and SO (the usual), and can't find if Node does or can expose Service Configuration settings in the same way. If not, is there a way I can expose them to my application?
Edit: To be more specific, I'm really only looking to move the node_env setting from web.config to Service Configuration, since I'd like to be able to switch from staging to production setup with just a config change. The reason - we're using IP switching to swap between staging and prod, and there are some very minor differences between the two (the URL of the RESTful web service it consumes, for example).
I also know I can configure node_env in an iisnode.yaml file read by iisnode, but that will still recycle the application, and I don't want to modify x yaml files and redeploy, where x is the number of instances of the production/staging application.

You can access the configuration settings via the Azure SDK for Node.js.
To install:
npm install azure
To get the configuration settings:
var azure = require('azure');
azure.RoleEnvironment.getConfigurationSettings(function(error, settings) {
if (!error) {
// You can get the value of setting "setting1" via settings['setting1']
}
});

These settings seem to be held in an XML file located in c:\Config\ folder of the Azure machine.
I'm certain that you're not supposed to access these directly, but you could easily parse this XML and read the settings when node starts.

Related

How to Load Azure App Service Application Settings into VUE?

We have a Vue app hosted as an Azure App Service. Under Settings\Configuration in Azure Portal We have added application settings like VUE_APP_API_ENDPOINT_URL. These become environment variables like the documentation explains, and can be verified by opening a console from the portal and type 'env'.
I Had hoped that These env variables would now be accessible inside Vue by use of
process.env.VUE_APP_API_ENDPOINT_URL
My guess is that its only becomes available in VUE when aplication is build with WebPack or similar.
At least it doesn't work.
Are there any nice way to read those env variables created from Azure App Settings into the vue app?
Some people mentions dotenv npm package, but we need to read the env variables not add them from a config file.
You would be correct that the Environment Variables only become available when you build the application. And to elaborate on that, only the Environment Variables that you specify/supply at build time are the ones that become available in the application from the build process as per the documentation here:
https://cli.vuejs.org/guide/mode-and-env.html#environment-variables
Specifically look at this:
Note that only NODE_ENV, BASE_URL, and variables that start with VUE_APP_ will be statically embedded into the client bundle with webpack.DefinePlugin. It is to avoid accidentally exposing a private key on the machine that could have the same name.
I was struggling to accomplish essentially the same thing that you're trying to accomplish. I was trying to get a value from Azure's Application Settings so that I could setup multiple environments for my application and not have to constantly change values depending on the environment I published the app to.
After realizing that you might be onto something and reading the confirmation of such in the documentation, I decided to try putting the Environment Variable that I was trying to get from Azure's Application Settings in a .env file with a default so that it would be specified at build time. I then published my app to Azure and tested it and it worked!
Try creating a .env file with all of the Azure Application Settings that you're trying to set with default values or something, like:
VUE_APP_API_ENDPOINT_URL=default_value
And then set those same variables into your Azure Application Settings with the proper values and it should work.
Zoull's comment, while somewhat factual, is not possible. His comment implies that setting VUE_APP_API_ENDPOINT in Azure's Static App Settings blade will seamlessly include that var, and perhaps other VUE_APP_* vars into the vue app.
This is wrong.
Webpack is responsible for inclusion of VUE_APP_* vars into the build, and this is only possible at build-time.
This can be verified by following his logic, and then dumping to console "env" at runtime. Values will be set to, permanently, whatever they were at build-time.
tl;dr: Vue will never read, post-build, vars from Application Settings.
I use Github actions to build and deploy. By adding an env: setting after the with: stanza, and including VUE_APP_* vars there, I can do what OP is trying to do.
I believe I can also set some github "secrets" in githubs settings for my repo, and also include them dynamically in the YAML.
Ex. If I have a github secret key/val of: "VUE_APP_FOO: true", in my github action yml, I can do:
env:
VUE_APP_FOO: ${{secrets.VUE_APP_FOO}}
Then, in my final vue build, I should have a value of "true" when I read the process.env.VUE_APP_FOO var.
Savvy?

Set up Azure Application Insights for local environment

We have set up Application Insights for our Dev & Prod environments, not with the SDK but through the Portal. We're now in the process of installing the SDK so we can have more control over customizing logging, what to measure in performance, etc.
I have found how to separate the environments in code (separate Instrumentation Key in different config files etc), but I have found nothing when it comes to my local environment. Which instrumentation key should I use there, the dev one? Wouldn't then this skew our dev metrics everytime one of the developers runs the app locally?
And also, doesn't it make sense to have a separate App Service slot just for the local environment, so I can test everything and see the logs I'm trying out locally, and not have to deploy to dev everytime I want to see what I'm doing?
I've tried creating a separate slot for local, but it generates a weird url based on the name I give, which I can't change later.
I've googled for a couple of days already and couldn't find any (or very little) helpful advice when it comes to this.
I realise there is a "Just add the SDK to try local only mode" option in Visual Studio, but then I would have to use it exclusively locally. What I want is to use all three - my local, dev & prod.
We're using .net core 2.2 for our backend and Angular 7 for front end.
I'm an idiot.
The url set up automatically basically means nothing. I solved the problem by just adding another App Service slot (created from our App Service production one, just like dev), and added this key to the local settings in our project.
Now we can use this key to get real time results as we debug, and use the other two for dev & production.

Reloadable custom config for ASP.NET Core app hosted on Azure App Service

I need to expose few simple configuration options for my website, that should be easy to change, without requiring recompilation or restarting the app. I'd also like the options to be cached in the app, but they should refresh when the config is changed (or at least every few minutes). My website is an ASP.NET Core MVC app, which runs on Azure App Service and is deployed by pushing to a git repository and then rebuilt using Kudu.
I was thinking about using Configuration with an EF provider, but it requires quite a bit of work to support reloading of the config when the data is changed.
I noticed that JSON config provider has "reloadOnChange" option, so this seems like a good candidate. However, I'm not sure where I should put the JSON file on the Azure App Service environment so it's easily readable by the app, shared across all instances and persistent between deploys. I know that the "d:\home" folder is shared and persistent. The wwwroot is inside of it, but I'm afraid that the file might get deleted at some point when the app is redeployed. So I'd like to put it in one of the parent folders, but how do I access the home folder from the C# code? I'm assuming I shouldn't just hardcode the "d:\home" path.
I'm also very keen to hear about any alternative ways to achieve the goal.
Actually, you do not need to worry that it will delete appsetting.json file when you redeployed. If you change your configurations, it will override the json file.
var configuration = new ConfigurationBuilder()
.SetBasePath(System.IO.Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddEnvironmentVariables()
.Build();
Note: When you publish the app, remember do not click "Remove additional files at destination".
Also, if you want to set the appsetting.json in home folder, you could use Environment.GetEnvironmentVariable("Home"); which is equal to "D:\home".
And if you set like this, you need to set ASPNETCORE_ENVIRONMENT to distinguish your environment is azure or local.

Azure Service Configuration Files

So I have been banging my head against a wall on this one...I am trying to publish an Azure Web Role and I have two ServiceConfiguration files:
ServiceConfiguration.Cloud.cscfg
ServiceConfiguration.Local.cscfg
In my publish xml I have:
<AzureServiceConfiguration>Cloud</AzureServiceConfiguration>
So my assumption here is that when I publish it will use the Cloud cfg.
For working locally, under the emulator I have set the flag for local debugging to use Local.
However it would seem that this flag here also determines the cscfg to use for the cloud...so I am a little confused - is this the correct behavior or am I missing something? I really want to have a separate one for local as I have different values I need.
Update
Suddenly it started to work fine today. Didn't really change anything.
Tom, your publish XML configuration file is OK, and your publish to Azure will use the .Cloud.cscfg.
You can pick which of the configuration files you want to use when publishing (right click > Publish...), on the second screen (under Service configuration).
What you did for your local environment should work fine, and use the .Local.cscfg file.

VS2012 Web Deploy Package to create application pool

I have a web application project in VS2012 which I'm publishing using a "Web Deploy Package". I want this package to include app-pool settings, specifically creating an IIS app-pool and assigning the newly created application to it.
I'm familiar with the option "Include application pool settings used by this Web project" available when the project is configured to use an IIS instance (not IIS Express), but IIS configuration is not part of the project file, and thus not source controlled. What happens when somebody builds a deployment package on a machine that hasn't had IIS meticulously configured? Not ideal.
How else then, can I go about getting AppPool settings into my web deploy package? I understand that the appPoolConfig provider is IIS7+ only, I'm fine with that limitation. I've banged my head against this issue in the past and never found a solution. 18 months later, we've got a new VisualStudio version, and a new web-publishing-pipeline, are there new options to address this? Or maybe something I missed when I first tackled this problem?
Edit
OK, I'm seeing the following as options:
Configure my project to sync settings from an IIS instance. As mentioned, I'm not a fan of this given that it puts settings outside of the project, meaning the environment has to be meticulously configured to build + publish. Plus it drags along other IIS settings I don't want included.
Inject something into the web-publishing-pipeline (WPP) to modify the archive.xml. I've toyed with this in the past and had limited success. One problem is the pipeline isn't exactly co-operative with working directly on the archive.xml file, another problem is some of the more cryptic attributes involved, like MSDeploy.MSDeployProviderOptions which appears to have some Base64 encoded binary? No idea what to put in there.
Find an existing "provider" that can do what I want. I might be out of luck here, the appPoolConfig provider only seems to want to read / write IIS, not, say, an XML file of settings. Does anybody know otherwise?
Write my own "provider" to produce manifest output entries. I'm not sure, is it possible to write a custom provider that writes to a manifest using the name of an existing provider? As in, MyCustomPoolProvider writes appPoolConfig sections into a manifest? This sounds like a potentially painful exercise that may or may not work. Would I still need to figure out the encoding of whatever is going into MSDeploy.MSDeployProviderOptions?
I get the feeling that the fundamental obstacle with Web Deploy for what I'm trying to accomplish, is how strictly it leans on "providers". The pre-existing providers are largely designed for IIS synchronisation, not primary development and publication. It so happens that some of these providers can be relatively easily hooked into via MSBuild, but the majority insist on pulling data from IIS, and that's that.
You are correct in your understanding of the appPoolConfig provider, in that it can only sync between App Pools and can't be provided with the configuration directly. What you could potentially do is keep a copy of the appPool in question in package form (ie. msdeploy -verb:sync -source:appPoolConfig=PoolName -dest:package=apppool.zip) and attempt to hijack the pipeline so that the MSDeploy call adds the application content into the package, leaving the existing content there.
Alternatively, you could always keep the packages separate and deploy them with different calls to MSDeploy.
FYI, MSDeploy.MSDeployProviderOptions is simply an encoded version of the parameters supplied to the provider when it was packaged. For example, -source:dirPath=c:\,ignoreErrors=0x10293847 -dest:package=package.zip would package the ignoreErrors value.

Resources