New (2022) Azure SDK .net - Get private IP address of VM primary network interface - azure-sdk-.net

by following the instructions provided here Quickstart Tutorial - Resource Management,
I am trying to find a way to get the private IP address of a VM but it looks like the VirtualMachineResource does not expose any related property.
With the old SDK it was pretty straight forward but with the new SDK it does not seem possible. Can anybody help me?
Thanks

thanks for the suggestions. I had to dig into the properties of the VirtualMachineResource class and in the end I got it. Here a code snippet. For simplicity's sake I am assuming that the VM has only one network interface, which has only one IP configuration.
var subscriptionId = "...";
var resourcegroup = "...";
var vmName = "...";
ArmClient client = new ArmClient(new DefaultAzureCredential());
var subscriptionIdentifier = SubscriptionResource.CreateResourceIdentifier(subscriptionId);
SubscriptionResource subscription = client.GetSubscriptionResource(subscriptionIdentifier);
var rg = subscription.GetResourceGroup(resourcegroup);
var vm = rg.Value.GetVirtualMachine(vmName);
var networkInterfaceReference = vm.Value.Data.NetworkProfile.NetworkInterfaces.Single();
var networkInterfaceResource = client.GetNetworkInterfaceResource(new ResourceIdentifier(networkInterfaceReference.Id));
var privateIpAddress = networkInterfaceResource.GetNetworkInterfaceIPConfigurations().Single().Data.PrivateIPAddress;

For virtual machines a private IP address or addresses are assigned to one or more network interfaces.
VirtualMachineResource does not expose any related property.
Yes, Virtual Machine Resources does not provide any related property. The private IP address of virtual machine scale set instances cannot be obtained. The network interfaces of virtual machine scale sets are not Azure resources and cannot be obtained.
You can use the REST API to achieve.
Refer to Get all azure VM's with all their Private and Public IP's
Get private IP address of VM primary network interface
To get the Private IP address you can use the PrimaryIPConfiguration and PrimaryPrivateIP properties.
Refer Latest Azure SDK for .NET - VMSS Network Interface Properties and Methods

Related

Connection to external Kafka Server using confluent-kafka-dotnet fails

I need to read Kafka messages with .Net from an external server. As the first step, I have installed Kafka on my local machine and then wrote the .Net code. It worked as wanted. Then, I moved to the cloud but the code did not work. Here is the setup that I have.
I have a Kafka Server deployed on a Windows VM (VM1: 10.0.0.4) on Azure. It is up and running. I have created a test topic and produced some messages with cmd. To test that everything is working I have opened a consumer with cmd and received the generated messages.
Then I have deployed another Windows VM (VM2, 10.0.0.5) with Visual Studio. Both of the VMs are deployed on the same virtual network so that I do not have to worry about opening ports or any other network configuration.
then, I have copied my Visual Studio project code and then changed the IP address of the bootstrap-server to point to the Kafka server. It did not work then, I read that I have to change the server configuration of Kafka, so I opened the server.properties and modified the listeners property to listeners=PLAINTEXT://10.0.0.4:9092. It still does not work.
I have searched online and tried many of the tips but it does not work. I think first of all to provide the credential to an external server (vm1), and probably some other configuration. Unfortunately, the official documentation of confluent is very short with very few examples. There is also no example to my case on the official GitHub. I have played with the "Sasl" properties in the Consumer Config class, but also no success.
the error message is:
%3|1622220986.498|FAIL|rdkafka#consumer-1| [thrd:10.0.0.4:9092/bootstrap]: 10.0.0.4:9092/bootstrap: Connect to ipv4#10.0.0.4:9092 failed: Unknown error (after 21038ms in state CONNECT)
Error: 10.0.0.4:9092/bootstrap: Connect to ipv4#10.0.0.4:9092 failed: Unknown error (after 21038ms in state CONNECT)
Error: 1/1 brokers are down
Here is my .Net core code:
static void Main(string[] args)
{
string topic = "AzureTopic";
var config = new ConsumerConfig
{
BootstrapServers = "10.0.0.4:9092",
GroupId = "test",
//SecurityProtocol = SecurityProtocol.SaslPlaintext,
//SaslMechanism = SaslMechanism.Plain,
//SaslUsername = "[User]",
//SaslPassword = "[Password]",
AutoOffsetReset = AutoOffsetReset.Latest,
//EnableAutoCommit = false
};
int x = 0;
using (var consumer = new ConsumerBuilder<Ignore, string>(config)
.SetErrorHandler((_, e) => Console.WriteLine($"Error: {e.Reason}"))
.Build())
{
consumer.Subscribe(topic);
var cancelToken = new CancellationTokenSource();
while (true)
{
// some tasks
}
consumer.Close();
If you set listeners to a hard-coded IP, it'll only start the server binding and accepting traffic to that ip
And your listener isn't defined as SASL, so I'm not sure why you've tried using that in the client. While using credentials is strongly encouraged when sending data to cloud resources, it's not required to fix a network connectivity problem. You definitely shouldn't send credentials over plaintext, however
Start with these settings
listeners=PLAINTEXT://0.0.0.0:9092
advertised.listeners=PLAINTEXT://10.0.0.4:9092
That alone should work within the VM shared network. You can use the console tools included with Kafka to test it.
And if that still doesn't work from your local client, then it's because 10.0.0.0/8 address space is considered a private network and you must advertise the VM's public IP and allow TCP traffic on port 9092 through Azure Firewall. It'd also make sense to expose multiple listeners for internal Azure network and external, forwarded network traffic
Details here discuss AWS and Docker, but the basics still apply
Overall, I think it'd be easier to setup Azure EventHub with Kafka support

How to get an instance by it's name using googleapiclient

I am using the googleapiclient.discovery as client to connect to GCP. Ideally, I would like to retrieve a virtual machine by it's
zone
project
name
I am having a difficult time finding code samples that do this. I am initializing the client like so
client = googleapiclient.discovery.build('compute', 'v1')
I've exported the environment variable GOOGLE_APPLICATION_CREDENTIALS and I am able to successfully connect to GCP. However, I am unable to fetch an instance by it's name. I am looking for a method like
instance = client.compute.instances().get("project","zone","instance_name")
Any help with this would be greatly appreciated.
Just need to set up a client with discovery like so
compute = discovery.build('compute', 'v1', credentials=credential)
getinstance = compute.instances().get(project=project_id, zone=region, instance=instance_id).execute()

Is there a way to not allocate an elastic IP (EIP) when creating a VPC using aws-cdk

I'm using the following code to create subnets that will be imported by another stack and used for a dedicated EFS VPC. If I don't create a PUBLIC subnet I get errors on creation. However the side effect is this code allocates an elastic IP address and I don't want one allocated, they are a precious resource.
How do I get rid of the elastic IP address? None of the methods allow you get anything that has an EIP attribute or method:
const fileSystemVpc = new ec2.Vpc(this, 'vpcForEfs', {
subnetConfiguration: [
{
cidrMask: 20,
name: 'nfsisolated',
subnetType: ec2.SubnetType.ISOLATED,
},
{
cidrMask: 20,
name: 'nfsprivate',
subnetType: ec2.SubnetType.PRIVATE,
},
{
cidrMask: 20,
name: 'nfspublic',
subnetType: ec2.SubnetType.PUBLIC,
},
],
});
If I comment out the PUBLIC section I get the following error on creation:
If you configure PRIVATE subnets in 'subnetConfiguration', you must also
configure PUBLIC subnets to put the NAT gateways into (got
[{"cidrMask":20,"name":"nfsisolated","subnetType":"Isolated"},
{"cidrMask":20,"name":"nfsprivate","subnetType":"Private"}].
Relevant issues that don't solve the problem but are similar:
https://github.com/aws/aws-cdk/issues/1305
https://github.com/aws/aws-cdk/issues/3704
This is the commit that added that check: https://github.com/aws/aws-cdk/commit/9a96c37b225b135c9afbf523ed3fbc67cba5ca50
Essentially if CDK wasn't stopping you with that message it would fail when CloudFormation tried to deploy the stack.
Here is more info from AWS on it as well: https://docs.aws.amazon.com/vpc/latest/userguide/vpc-nat-gateway.html
You can see the description of the ticket that was referenced in it and the AWS docs, if whatever you want to put in the PRIVATE subnets doesn't require internet access you should be using ISOLATED instead. This is because a PRIVATE subnet requires a NatGateway and a NatGateway is required to exist in a PUBLIC subnet with an elastic IP. Again, if you don't require outbound access to the internet from your PRIVATE subnet just use ISOLATED

Service Fabric Naming Service not forwarding to endpoint assigned to Guest Executable

I have setup an application with two services, one a standard aspnet core api, and another node express app by following the guide here:
https://learn.microsoft.com/en-us/azure/service-fabric/service-fabric-deploy-existing-app
When I deploy the application locally I can use the naming service to hit the AspNetCore application such as:
http://localhost:19081/sf_node_test_02/AspNetCore/api/values
Likewise, I expect to be able to hit the api of my guest executable using this address:
http://localhost:19081/sf_node_test_02/NodeApp
However, this does not work.
If I use the direct url of the service such as:
http://localhost:30032/ I can see the node js app is in fact working as expected.
Now, I know when running the AspNet core application it is explicitly sending it's listening address back to the naming service but the guest executable is not so that explains why they might behave differently. Also, from what I understand the current version of service fabric does not provide the guest executable the information about a dynamically assigned port so it must be hard coded in the service endpoint and also in the application to listen on the same port.
E.g. If I have:
<Endpoint Name="NodeAppTypeEndpoint" Port="30032" Protocol="http" Type="Input" UriScheme="http"/>
Then in the nodejs app I must also have:
const port = process.env.PORT || 30032;
app.listen(port, () => {
console.log(`Listening on port: ${port}`);
});
Noticed 30032 in both places.
From the documentation:
Furthermore you can ask Service Fabric to publish this endpoint to the
Naming Service so other services can discover the endpoint address to
this service. This enables you to be able to communicate between
services that are guest executables. The published endpoint address is
of the form UriScheme://IPAddressOrFQDN:Port/PathSuffix. UriScheme and
PathSuffix are optional attributes. IPAddressOrFQDN is the IP address
or fully qualified domain name of the node this executable gets placed
on, and it is calculated for you.
I interpreted this to mean that if my ServiceManifest.xml has both UseImplicitHost="true" then it should automatically give the naming service the url constructed by the endpoint description.
http://localhost:19081/sf_node_test_02/NodeApp -> http://localhost:30032
Is it correct that service fabric will automatically give the naming service this listening address for this service?
Is there anyway for me to inspect the mapping in the naming service?
This would let me know if it does have an entry for my node application but it is just different than what I expect or if in fact it has no entry.
If it doesn't have an entry then I don't know how this guest executable application would be visible to the public when deployed in the cloud either.
You can use the QueryManager of FabricClient to list registered endpoints for services in your cluster. This should reveal if there is an endpoint for your node service.
var fabricClient = new FabricClient();
var applicationList = fabricClient.QueryManager.GetApplicationListAsync().GetAwaiter().GetResult();
foreach (var application in applicationList)
{
var serviceList = fabricClient.QueryManager.GetServiceListAsync(application.ApplicationName).GetAwaiter().GetResult();
foreach (var service in serviceList)
{
var partitionListAsync = fabricClient.QueryManager.GetPartitionListAsync(service.ServiceName).GetAwaiter().GetResult();
foreach (var partition in partitionListAsync)
{
var replicas = fabricClient.QueryManager.GetReplicaListAsync(partition.PartitionInformation.Id).GetAwaiter().GetResult();
foreach (var replica in replicas)
{
if (!string.IsNullOrWhiteSpace(replica.ReplicaAddress))
{
var replicaAddress = JObject.Parse(replica.ReplicaAddress);
foreach (var endpoint in replicaAddress["Endpoints"])
{
var endpointAddress = endpoint.First().Value<string>();
Console.WriteLine($"{service.ServiceName} {endpointAddress} {endpointAddress}");
}
}
}
}
}
}

BOSH working with Dynamic IP Addresses

What's the best way to work with dynamic IP addresses with BOSH? Currently we're setting static IP addresses for each machine we want to use, but we only really care that one of those VMs has a static IP address.
Is there a way to get information about other VMs running in the BOSH network from within a BOSH VM? Or just get dynamic information about the deployment from within the VM? Such as which machines are currently running on which IP addresses?
It sounds like the recent introduction of "links" is worth a look for your use case.
Previously, if network communication was required between jobs, release authors had to add job properties to accept other job’s network addresses (e.g. a db_ips property). Operators then had to explicitly assign static IPs or DNS names for each instance group and fill out network address properties
This lets each job either expose or consume connections.
i.e. a DB exposes its connection
# Database job spec file.
name: database_job
# ...
provides:
- name: database_conn
type: conn
# Links always carry certain information, like its address and AZ.
# Optionally, the provider can specify other properties in the link.
properties:
- port
- adapter
- username
- password
- name
And a Application can consume it.
# Application job spec file.
name: application_job
# ...
consumes:
- name: database_conn
type: conn
The consuming job is provided with extra properties to use these addresses/info as needed, i.e.
#!/bin/bash
# Application's templated control script.
# ...
export DATABASE_HOST="<%= link('database_conn').instances[0].address %>"
export DATABASE_PORT="<%= link('database_conn').p('port') %>"