I am attempting to interpolate API username and password into my appsettings.json using Circle CI. I have placeholder values "ApiUsernamePlaceholder" and "ApiPasswordPlaceholder" that correspond to "Username" and "Password" fields in the json, like so:
"API": {
"URL": "https://some.url.com/api",
"username": "ApiUsernamePlaceholder",
"password": "ApiPasswordPlaceholder"
}
Is it possible, using Circle CI, to substitute the placeholders with an actual value at runtime? I have found conflicting statements on the issue, and the documentation is not clear.
This is a .Net Core 2.0 C# API project.
Yes. Like on any Unix-based environment, during your build use sed to swap out the place holders for the value of private environment variables that you'd set via the CircleCI webapp.
Related
I have this array in my appsettings.json:
"ServiceDefinitions": [
{
"Name": "encryption-api",
"Url": "http://localhost:5032",
"ApiKey": "",
"ExposedEndpoints": [
"encrypt",
"decrypt"
]
}
],
I want to be able to override this with an environment variable. I've added the env vars to the configuration builder like this, which seems to work for other values:
builder.Configuration.AddEnvironmentVariables();
And then I've attempted to set this in my Docker Compose file with:
environment:
- ASPNETCORE_URLS=http://gateway:8080/
- ServiceDefinitions="{\"Name\":\"encryption-api\",\"Url\":\"http://encryption-api:80\",\"ApiKey\":\"\",\"ExposedEndpoints\":[\"encrypt\",\"decrypt\"]}"
However, it's still picking up the value from the json file rather than the env var. I've also tried setting it inside [] but that makes no difference.
How can I do this?
Microsoft docs regarding app configuration.
You are going to want to make sure that your Json provider is registered before your environment variables provider. Then you'll want to setup your environment variables in your Docker file as follows:
environment:
- ASPNETCORE_URLS=http://gateway:8080/
- ServiceDefinitions__0__Name="encryption-api"
- ServiceDefinitions__0__Url="http://encryption-api:80"
- ServiceDefinitions__0__ApiKey=""
- ServiceDefinitions__0__ExposedEndpoints__0="encrypt"
- ServiceDefinitions__0__ExposedEndpoints__1="decrypt"
I amp attempting to create a new mapbox style via the mapbox api. When the create process completes, I am getting a success confirmation back, but I cannot use or view the style after it is created. Based on these docs and these docs, I am sending a payload to this api endpoint:
https://api.mapbox.com/styles/v1/[accountname]
The payload I am sending is this:
{
"version": 8,
"name": "mystyle via api",
"sprite": "mapbox://sprites/mapbox/bright-v8",
"metadata": null,
"sources": {
"mapbox-streets": {
"type": "vector",
"url": "mapbox://mapbox.mapbox-streets-v6"
}
},
"glyphs": null,
"layers": []
}
After sending this payload to the mapbox api, I receive this message back:
{
"version": 8,
"name": "mystyle via api",
"metadata": null,
"sources": {
"mapbox-streets": {
"type": "vector",
"url": "mapbox://mapbox.mapbox-streets-v6"
}
},
"sprite": "mapbox://sprites/[accountname]/ckby5s52p2r9v1hmwgkrzenvw/3teom2ial2ryn2u97lclizpce",
"glyphs": "mapbox://fonts/[accountname]/{fontstack}/{range}.pbf",
"layers": [],
"created": "2020-06-27T21:30:49.047Z",
"id": "ckby5s52p2r9v1hmwgkrzenvw",
"modified": "2020-06-27T21:30:49.047Z",
"owner": "[accountname]",
"visibility": "private"
}
Then I proceed to my account in the portal and I see my new style:
However, something is wrong. The preview icon shows just a transparent graphic. And when I click on the style to view/edit it, I get this cryptic error message "Cannot read property 'mapbox:decompiler' of null":
What am I missing here? I am finding the documentation for this process very spread out through several documents. But I am copying the examples in the snippets verbatim
This is a "valid" style, but it has no layers (see the last field of the JSON), that's why it doesn't display anything. (I know this is verbatim from the example in the Create a style docs)
The key concept here to master is the difference between Sources and Layers. Sources are "data sources": you won't see them unless you have a Layer displaying it. Some types of Sources can contain many layers (see the source-layer property in the Layer object), and/or you might want to display the same source with different stylings across different maps. That's one reason they are separated.
Or, as the Sources docs put it:
Adding a source isn't enough to make data appear on the map because sources don't contain styling details like color or width. Layers refer to a source and give it a visual representation. This makes it possible to style the same source in different ways, like differentiating between types of roads in a highways layer.
Combining the Style object sample with the Layer object sample would give you something like this:
{
"version": 8,
"name": "mystyle via api",
"sprite": "mapbox://sprites/mapbox/bright-v8",
"metadata": null,
"sources": {
"mapbox-streets": {
"type": "vector",
"url": "mapbox://mapbox.mapbox-streets-v6"
}
},
"glyphs": null,
"layers": [
{
"id": "water",
"source": "mapbox-streets",
"source-layer": "water",
"type": "fill",
"paint": {
"fill-color": "#00ffff"
}
}
]
}
Now, keep in mind that the global Mapbox styles contain several layers (maybe up to a couple dozen), with very fine settings such as what type of features should show at which zoom level and with what configurations, etc. Most applications should not need to recreate those from scratch.
If you want to overlay dynamic data (to be decided at runtime), you can use one of the global styles and dynamically add a Layer on top of an untouched default style. The link is for Mapbox GL JS, assuming the UI is browser-based. If the UI is a mobile app, there are corresponding methods in the iOS and Android SDKs.
Now, if you don't need dynamic data at all, consider Mapbox Studio instead. This will allow you to create a custom style (with the default styles as templates if you want) and add/remove layers. For example, if mapbox://styles/mapbox/streets-v11 is almost a perfect fit, but you don't need to (say) show small town names, you can create a custom template in Mapbox Studio and remove just that. In the end, it will you give you a style ID which you can just put into your map like a default (global) style.
Also note that, depending on your case, you may combine both approaches.
What does actually Using do in Serilog JSON configuration (e.g. in AppSettings.json file in .Net Core environment)?
Let us take this configuration for example:
"Serilog": {
"Using": [ "Serilog.Sinks.Console" ], <=======***HERE***=========
"MinimumLevel": "Debug",
"WriteTo": [
{ "Name": "Console" },
{
"Name": "RollingFile",
"Args": {
"pathFormat": "logs\\log-{Date}.txt",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] {Message}{NewLine}{Exception}"
}
}
],
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
"Properties": {
"Application": "My Application"
}
}
In the example above we used File sink WITHOUT adding it to Using attribute. However, everything seems to be working ok.
So I cannot understand exactly why we basically need this Using. Could someone explain it to me please?
This is covered in the documentation for Serilog.Settings.Configuration:
(This package implements a convention using DependencyContext to find any package with Serilog anywhere in the name and pulls configuration methods from it, so the Using example above is redundant.)
This means that it's used to define which packages are used for locating Serilog sinks, but it's redundant when using the Serilog.Settings.Configuration package.
More Information
I've had a look at the Serilog source code in order to be able to provide more information on exactly what Using does and why it might be needed in the first place. I hope the following explanation is helpful.
Consider the following code-based setup:
Log.Logger = new LoggerConfiguration()
.WriteTo.Console()
.CreateLogger();
In this example, Console is an extension method for LoggerSinkConfiguration (and so it takes, as its first parameter, an instance of LoggerSinkConfiguration). When using this code-based approach, the code will only compile if this extension method can be found within a referenced assembly.
Next, consider the following approach, which uses the IConfiguration-based approach:
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(someConfiguration)
.CreateLogger();
{
"Serilog": {
"Using": ["Serilog.Sinks.Console"], // Redundant.
"WriteTo": ["Console"]
}
}
In this example, the compilation process has no knowledge of what the JSON string value "Console" refers to and so there's a need for a process that can go from the string "Console" to the Console() extension method mentioned above. In order to do that, Serilog needs to first find the extension method at runtime (which, in this example, lives in the Serilog.Sinks.Console assembly).
This finding process is done using reflection, which does a bit of assembly scanning to find public static methods that take as their first parameter a LoggerSinkConfiguration. The Using directive you've asked about in your question is a mechanism for helping determine exactly which assemblies should be scanned when looking for these extension methods.
As the documentation states, the IConfiguration-based approach uses DependencyContext in order to automatically scan assemblies that have Serilog in their name. Because Serilog.Sinks.Console does have Serilog in its name, there's no need to add this to the Using directive. You also have the option to provide your own DependencyContext instance when using this approach and so you might then need to be explicit about which assemblies to scan when looking for sinks.
I'm trying to add some custom binding using my app settings for my Azure Function. I need to receive only string a string from my settings.
I would like to get simpleValue from my settings.
{
"bindings": [
{
"name": "someValue",
"type": "stringSetting",
"connection": "simpleValue",
"direction": "in"
}
],
"disabled": false
}
and the get it in Run method:
static void GetOrders(TraceWriter log, string someValue)
{
log.Info(someValue);
}
Is it even possible. Maybe there is other way to do it?
I already found the solution. Just add:
using System.Configuration;
and add this line to code with the key ("simpleValue") value:
ConfigurationManager.AppSettings["simpleValue"]
App Settings configurations can be referred in binding json as %MY_CUSTOM_CONFIG% - enclosed within percent symbols.
Note that the connection property of triggers and bindings is a
special case and automatically resolves values as app settings,
without percent signs.
https://learn.microsoft.com/en-us/azure/azure-functions/functions-triggers-bindings
I'd like to create an Azure Function that is triggered when a new message is added to a topic/subscription.
For the moment I've created an Azure Function using the ServiceBusQueueTrigger C# Template and I've set the Queue Name to
topicPath + "/Subscriptions/" + subscriptionName
But I've got this exception:
Microsoft.ServiceBus: Cannot get entity 'topic-test/Subscriptions/subscription-test' because it is not of type QueueDescription. Check that you are using method(s) with the correct entity type. System.Runtime.Serialization: Error in line 1 position 1762. Expecting element 'QueueDescription' from namespace 'http://schemas.microsoft.com/netservices/2010/10/servicebus/connect'.. Encountered 'None' with name '', namespace ''. .
I thought the Azure Function was using the MessagingFactory.CreateMessageReceiver to initialize the message pump but not.
Is there any support for topic/subscription for the moment ?
Yes topics are supported, but our UI and templates are behind on that unfortunately - we'll be releasing some updates soon addressing these issues.
For now, you can use the Advanced Editor to edit your trigger binding directly. There you can specify your subscriptionName and topicName values. Here's an example:
{
"bindings": [
{
"type": "serviceBusTrigger",
"name": "message",
"direction": "in",
"subscriptionName": "subscription-test",
"topicName": "topic-test",
}
]
}
In general, since Azure Functions is build atop the WebJobs SDK, our various bindings are mapped directly to their SDK counterparts. For example serviceBusTrigger maps to ServiceBusTriggerAttribute which has SubscriptionName/TopicName properties. Therefore, expect to see the same properties in the Function metadata model.