Read AzureDevOps Pipeline Variables in C# - .net-core

I need develop a C# .NetCore Console Application to access my DevOps account, select a release and read all variables in Pipeline Variables[
Anybody can give me an example?

Found a solution do read variables from Azure DevOps with REST API.
https://learn.microsoft.com/en-us/rest/api/azure/devops/?view=azure-devops-rest-6.1

Here I have a rough draft to read the variables from a release definition. You can create the .NET helper objects by creating helper classes from the JSON. There are sites on the internet for this.
Main() {
var pat = Environment.GetEnvironmentVariable("????");
var baseUrl = "https://dev.azure.com/{organization}";
var apiversion = "api-version=6.0";
var project = "????";
var search = "Releasename";
var actUrl = string.Format("{0}/{1}/_apis/release/definitions?searchText={2}&{3}",baseUrl,project,search,apiversion);
var json = await GetJsonFromUrlPAT(actUrl, pat);
cReleases varReleases = JsonConvert.DeserializeObject<cReleases>(json);
int ReleaseId=0;
if (varReleases.count == 1)
{
ReleaseId = varReleases.values[0].id;
actUrl = string.Format("{0}/{1}/_apis/release/definitions/{2}?{3}",baseUrl,project,ReleaseId,apiversion);
var json2 = await GetJsonFromUrlPAT(actUrl, pat);
cReleasedefinition varReleaseDef = JsonConvert.DeserializeObject<cReleasedefinition>(json2);
string jsonstring = JsonConvert.SerializeObject(varReleaseDef);
foreach (KeyValuePair<String,JToken> element in varReleaseDef.variables)
{
string varname = element.Key;
string varvalue = ((JObject)(element.Value)).GetValue("value").ToString();
}
foreach (var element in varReleaseDef.environments)
{
string environmentname = element.name;
foreach (KeyValuePair<String, JToken> item in element.variables)
{
string varname = item.Key;
string varvalue = ((JObject)(item.Value)).GetValue("value").ToString();
}
}
}
}

No worries!
To get your pipeline variables applied to your application configuration, you're going to want to use the File Transform task within your pipeline and configure it to point to your configuration JSON file within the Target Files
File Transform Task: https://learn.microsoft.com/en-us/azure/devops/pipelines/tasks/utility/file-transform?view=azure-devops
What this task is going to do is use the variables you've associated with your pipeline to replace values within your JSON configuration.
Some things to note when using File Transform:
It can only perform replace operations, it cannot add to your configuration. So, be sure to have placeholders for every value you are looking to replace within your JSON file.
To access a nested value within JSON, you want to use a period within your naming conventions. In your case for example, you'll want to change ConnectionStrings:StorageAccountLogs to **ConnectionStrings.StorageAccountLogs" ** in order to correctly perform the variable substitution.

Related

Azure Resource Manager DNS: Sample code to create a DNS record

I'm currently trying to move out from using old Microsoft.Azure.Management.Dns package to the new Azure.ResourceManager.Dns.
However I've been having issues in our code that creates Dns records such as an Arecord.
I've tried to go through the official documentation https://learn.microsoft.com/en-us/dotnet/api/azure.resourcemanager.dns.dnsarecordcollection.createorupdate?view=azure-dotnet
But the classes that represent an Arecord are either read only or private so I have no idea how to update this simple lines:
RecordSet set = DnsManagementClient.client.RecordSets.Get(resourceGroupName, zone, recordSetName, RecordType.A);
set.ARecords = set.ARecords ?? new List<ARecord>();
set.ARecords.Add(new ARecord(ipAddress));
DnsManagementClient.client.RecordSets.CreateOrUpdateWithHttpMessagesAsync(resourceGroupName, zone, recordSetName, RecordType.A, set, ifNoneMatch: "*");
Currently documentation only talks about Zones, can an example be added to the official documentation on how to add or update a DNS record (A,CNAME,etc..)
https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/dns/Azure.ResourceManager.Dns
I'm expecting a method to create an A record that let's you specify an IP address, and currently all the classes that potentially can be used to do that are either read-only or internal.
DnsARecordData has an internal list of Arecords, DnsARecordData.DnsARecords is where we can invoke the Add method to create the record. The reason DnsARecordData doesn't have a setter method is due to the .Net framework design guideline..
An example of how to create an A record using Azure.Resourcemanager.Dns can be found here:
// Create or update A record
string myARecordName = "myrecord";
DnsARecordData dnsARecordData = new() {TtlInSeconds = (long)TimeSpan.FromHours(1).TotalSeconds};
dnsARecordData.DnsARecords.Add(new DnsARecordInfo { IPv4Address = IPAddress.Parse("127.0.0.1") });
DnsARecordCollection dnsARecordCollection1 = dnsZoneResource.GetDnsARecords();
dnsARecordCollection1.CreateOrUpdate(WaitUntil.Completed, myARecordName, dnsARecordData);
// Create or update CName pointing to A record
string myCnameName = "mycname";
DnsCnameRecordData dnsCnameRecordData = new() { Cname = $"{myARecordName}.{DnsZone}", TtlInSeconds = (long)TimeSpan.FromMinutes(10).TotalSeconds, };
DnsCnameRecordCollection cnameRecordCollection = dnsZoneResource.GetDnsCnameRecords();
cnameRecordCollection.CreateOrUpdate(WaitUntil.Completed, myCnameName, dnsCnameRecordData);
I tried in my environment and got below results:
You can create A record set using Azure.ResourceManager.Dns package. The version of NuGet package is beta-1.
NuGet Package:
Azure.ResourceManager.Dns 1.0.0 beta-1
Code:
using Azure;
using Azure.Identity;
using Azure.ResourceManager;
using Azure.ResourceManager.Dns;
using Azure.ResourceManager.Resources;
using System.Net;
ArmClient armClient = new ArmClient(new DefaultAzureCredential());
SubscriptionResource subscription = await armClient.GetDefaultSubscriptionAsync();
// first we need to get the resource group
string rgName = "rg-name";
ResourceGroupResource resourceGroup = await subscription.GetResourceGroups().GetAsync(rgName);
string dnsZoneName = "dns name";
DnsZoneCollection dnsZoneCollection = resourceGroup.GetDnsZones();
DnsZoneData data1 = new DnsZoneData("Global")
{
};
ArmOperation<DnsZoneResource> lro = await dnsZoneCollection.CreateOrUpdateAsync(WaitUntil.Completed, dnsZoneName, data1);
DnsZoneResource dnsZone = lro.Value;
RecordSetACollection recordSetACollection = dnsZone.GetRecordSetAs();
string name = "cname1";
var parm = new ARecordSetData();
parm.TTL =600;
parm.ARecords = new List<ARecord>();
parm.ARecords.Add(new ARecord("1.2.3.4"));
ArmOperation<RecordSetAResource> recordSetAResource = recordSetACollection.CreateOrUpdate(WaitUntil.Completed, name,parm);
RecordSetAResource recordSetAs = recordSetAResource.Value;
Console:
Portal:
For more reference:
azure-sdk-for-net/Sample2_ManagingRecordSetPtrs.md at dvbb-mgmt-track2-dns-2 ยท dvbb/azure-sdk-for-net (github.com)

How can I optimize this function get all values in a redis json database?

My function
public IQueryable<T> getAllPositions<T>(RedisDbs redisDbKey)
{
List<T> positions = new List<T>();
List<string> keys = new List<string>();
foreach (var key in _redisServer.Keys((int)redisDbKey))
{
keys.Add(key.ToString());
}
var sportEventRet = _redis.GetDatabase((int)redisDbKey).JsonMultiGetAsync(keys.ToArray());
foreach (var sportEvent in sportEventRet.Result)
{
var redisValue = (RedisValue)sportEvent;
if(!redisValue.IsNull)
{
var positionEntity = JsonConvert.DeserializeObject<T>(redisValue, jsonSerializerSettings);
positions.Add(positionEntity);
}
}
return positions.AsQueryable();
}
Called as
IQueryable<IPosition> union = redisClient.getAllPositions<Position>(RedisDbs.POSITIONDB);
Where Position is a simple model with just a few simple properties. And RedisDbs is just an enum representing an int for a specific database. With both this application and the redisjson instance running locally on a high performance server, it takes two seconds for this function to return a database with 20k json values in it. This is unacceptable for my specific usecase, I need this to be done in the maximum of 1 second, preferably sub 600ms. Are there any optimizations I could make to this?
I'm convinced the problem is with the KEYS command.
Here is what is written about Keys command in redis.io:
Warning: consider KEYS as a command that should only be used in production environments with extreme care. It may ruin performance
when it is executed against large databases. This command is intended
for debugging and special operations, such as changing your keyspace
layout. Don't use KEYS in your regular application code.
You can save the list of your json keys and then use them in your function instead of calling the keys command.

Issue with providing data model to template with scriban on .net core

I am trying to generate a document from scriban template but no data is present in the output:
var template = Template.Parse("{{model.Data}}");
var renederdContent = template.Render(new {
model = new {
Data = "some string"
}
});
Yet the output is empty. This used to work perfectly on .net framework whereas on .net core I've got a problem.
It seems the behavior of Scriban is different here in .net core. It changes names by default to a different case. For instance "Data" is changes to "data" and "PriceChanged" changes to "price_changed". To left the names unchanged you need to call Render method like this:
var renederedContent = template.Render(new {
model = new {
Data = "some string"
},
m => m.Name
});

asp.net core 1.0 SQL Server connection string for production environment?

I am having a difficult time setting up a connection string to an Azure SQL database in a production environment.
I am trying to use system variables instead of the json/xml files.
var builder = new ConfigurationBuilder();
builder.AddEnvironmentVariables("environment_variable_name");
var config = builder.Build();
Services.AddDbContext<AppDBContext>(options => options.UseSqlServer(config.GetConnectionString("environment_variable_name")));
But that does not seem to be getting the value out of the environment variable.
Any idea what I am doing wrong?
When debugging, I see the config variable gets populated with the right key/value, however, config.GetConnectionString does not seem to work.
If the connection string is stored in env variable named environment_variable_name, then you can obtain it like this:
var builder = new ConfigurationBuilder();
builder.AddEnvironmentVariables("");
var config = builder.Build();
Services.AddDbContext<AppDBContext>(options =>
options.UseSqlServer(config["environment_variable_name"]));
There were two problems here:
GetConnectionString will look for configuration key ConnectionStrings:environment_variable_name, not environment_variable_name. So either you have to change your env variable name to ConnectionStrings:environment_variable_name or use config["environment_variable_name"] to obtain the value.
The first argument to AddEnvironmentVariables is not a variable name, but a prefix. This means that if I had env variables named my_application and my_connectionstring, the following code will get them:
var builder = new ConfigurationBuilder();
builder.AddEnvironmentVariables("my_");
var config = builder.Build();
var appname = config["application"];
var connstr = config["connectionstring];
This is useful, because you don't get your configuration cluttered with every possible environment variable, only filter those that you know you will be using. Note however that the prefix is stripped when accessing the variables.
In your example, if you have env variable named environment_variable_name, and use AddEnvironmentVariables("environment_variable_name");, then you could access its value with config[""].

ASP.NET MVC Reference script file with version wildcard (without bundling)

In a ASP.NET MVC 4 project, I'd like to reference a versioned script file like this:
// Just some pseudo-code:
<script src="#Latest("~/Scripts/jquery-{0}.min.js")"></script>
// Resolves to the currently referenced script file
<script src="/Scripts/jquery-1.10.2.min.js"></script>
so that when a new Script version is updated via NuGet, the reference is updated automatically. I know of the bundling-and-minification feature, but it's just to much. I just want the little part which resolves the wildcards. My files are already minified, and also I don't want the bundles.
Do you have some smart ideas how to solve this?
Even though it's a little over kill to use the Bundling in MVC, but I think that will be your best bet. It's already been done and proven so why spend more time to write some proprietary code.
That being said, if you want a simple sample of what you can do, then you can try the following.
public static class Util
{
private const string _scriptFolder = "Scripts";
public static string GetScripts(string expression)
{
var path = HttpRuntime.AppDomainAppPath;
var files = Directory.GetFiles(path + _scriptFolder).Select(x => Path.GetFileName(x)).ToList();
string script = string.Empty;
expression = expression.Replace(".", #"\.").Replace("{0}", "(\\d+\\.?)+");
Regex r = new Regex(#expression, RegexOptions.IgnoreCase);
foreach (var f in files)
{
Match m = r.Match(f);
while (m.Success)
{
script = m.Captures[0].ToString();
m = m.NextMatch();
}
}
return script;
}
}
This will return you the last match in your Scripts director or it will return empty string.
Using this call
#Html.Raw(MvcApplication1.Util.GetScripts("jquery-{0}.min.js"))
Will get you this result if 1.8.2 is the last file that matched your string.
jquery-1.8.2.min.js
Hope this will help you get started.

Resources