I'm try to get primary IP of virtual machine and I get error 'virtualMachine.GetPrimaryPublicIPAddress().IPAddress' threw an exception of type 'System.NullReferenceException'
I successfully to get IP by use Rest-API in Postman
e.g Postman GET Method
https://management.azure.com/subscriptions/{{subid}}/resourceGroups/{{rg}}/providers/Microsoft.Network/networkInterfaces/{{vm_name}}?api-version=2020-11-01
my code in .Net
var credentials = SdkContext.AzureCredentialsFactory
.FromServicePrincipal(clientId,
clientSecret,
tenantId,
AzureEnvironment.AzureGlobalCloud);
var azure = Azure
.Configure()
.WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic)
.Authenticate(credentials)
.WithSubscription(subscriptionId);
foreach (var virtualMachine in azure.VirtualMachines.ListByResourceGroup(resourceGroupName))
{
var name = virtualMachine.Name;
var os_type = virtualMachine.OSType;
var size = virtualMachine.OSDiskSize;
var ip = virtualMachine.GetPrimaryPublicIPAddress().IPAddress; //Error
}
Thanks for Help
Try this code:
using Microsoft.Azure.Management.Compute.Fluent;
using Microsoft.Azure.Management.Fluent;
using Microsoft.Azure.Management.ResourceManager.Fluent;
using Microsoft.Azure.Management.ResourceManager.Fluent.Core;
using System;
using System.Threading.Tasks;
namespace myVMDotnetProject
{
class Program
{
static void Main(string[] args)
{
GetVMInfo();
Console.WriteLine("okok");
Console.ReadLine();
}
static async Task GetVMInfo()
{
var credentials = SdkContext.AzureCredentialsFactory.FromFile(Environment.GetEnvironmentVariable("AZURE_AUTH_LOCATION", EnvironmentVariableTarget.User));
var azure = Azure
.Configure()
.WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic)
.Authenticate(credentials)
.WithDefaultSubscription();
IVirtualMachines _client = azure.VirtualMachines;
var list = await _client.ListAsync();
foreach (var instance in list)
{
var name = instance.Name;
var ip = instance.GetPrimaryPublicIPAddress().IPAddress;
Console.WriteLine("name: " + name + ", ip: " + ip);
}
}
}
}
Here is the result I test locally:
I am writing some simple C# code to try automatically getting HAR file from Chrome browser. I am using browser-mob-proxy and there is a function: GetHar() which is supposed to return some different entries of URL, request and response time, etc. However, it always return me only 1 entry which is the original URL I am negativing to: www.google.com
I've tried to use dr.Navigate().Refresh() to make sure the page is reloaded so there are some activities on chrome DevTool Network section.
server.Start();
Thread.Sleep(1000);
Client client = server.CreateProxy();
client.NewHar("google");
var chromeOptions = new ChromeOptions();
var seleniumProxy = new Proxy { HttpProxy = client.SeleniumProxy };
chromeOptions.Proxy = seleniumProxy;
var dr = new ChromeDriver(chromeOptions);
dr.Navigate().GoToUrl("http://www.google.com");
dr.FindElementByClassName("gb_e").Click();
Thread.Sleep(3500);
dr.Navigate().Refresh();
// Get the performance stats
HarResult harData = client.GetHar();
Log log = harData.Log;
Entry[] entries = log.Entries;
foreach (var e in entries)
{
Request request = e.Request;
Response response = e.Response;
var url = request.Url;
var time = e.Time;
var status = response.Status;
var testStr = "Url: " + url + " - Time: " + time + " Response: " + status;
}
I expected GetHar() function will return more entries instead of only 1.
Not sure why, but the issue has been resolved by adding SSL proxy:
var seleniumProxy = new Proxy { HttpProxy = client.SeleniumProxy , SslProxy = client.SeleniumProxy };
I am trying to send a push notification from an iOS device (iPhone) via Azure NotificationHub REST Api. I am attempting this from a Xamarin.iOS solution following the Azure documentation I found online.
Response returns following info:
Error: '50002: Provider Internal Error'
Status code: 500
Code used to invoke NotificationHub REST Api (from iOS client app):
var hubUtil = new NotificationHubUtility("Endpoint=sb://company-name.servicebus.windows.net/;SharedAccessKeyName=DefaultFullSharedAccessSignature;SharedAccessKey=00000000000000011111111111111122222222222222");
hubUtil.SendNotificationMessage("This is a TEST Notification!").ConfigureAwait(false);
public class NotificationHubUtility
{
public string Endpoint { get; private set; }
public string SasKeyName { get; private set; }
public string SasKeyValue { get; private set; }
public string HubName { get; private set; }
public string ApiVersion { get; private set; }
public NotificationHubUtility(string connectionString)
{
//Parse Connectionstring
string[] parts = connectionString.Split(new char[] {';'});
for (int i = 0; i < parts.Length; i++)
{
if (parts[i].StartsWith("Endpoint", StringComparison.CurrentCulture))
Endpoint = "https" + parts[i].Substring(11);
if (parts[i].StartsWith("SharedAccessKeyName", StringComparison.CurrentCulture))
SasKeyName = parts[i].Substring(20);
if (parts[i].StartsWith("SharedAccessKey", StringComparison.CurrentCulture))
SasKeyValue = parts[i].Substring(16);
}
HubName = "my-hub";
ApiVersion = "?api-version=2014-09-01";
}
public string GetSaSToken(string uri, int minUntilExpire)
{
string targetUri = Uri.EscapeDataString(uri.ToLower()).ToLower();
// Add an expiration in seconds to it.
long expiresOnDate = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
expiresOnDate += minUntilExpire * 60 * 1000;
long expires_seconds = expiresOnDate / 1000;
var toSign = targetUri + "\n" + expires_seconds;
// Generate a HMAC-SHA256 hash or the uri and expiration using your secret key.
IMacAlgorithmProvider hasher = WinRTCrypto.MacAlgorithmProvider.OpenAlgorithm(MacAlgorithm.HmacSha256);
var messageBuffer = WinRTCrypto.CryptographicBuffer.ConvertStringToBinary(toSign, Encoding.UTF8);
var keyBuffer = WinRTCrypto.CryptographicBuffer.ConvertStringToBinary(SasKeyValue, Encoding.UTF8);
var hmacKey = hasher.CreateKey(keyBuffer);
var signedMessage = WinRTCrypto.CryptographicEngine.Sign(hmacKey, messageBuffer);
string signature = Uri.EscapeDataString(WinRTCrypto.CryptographicBuffer.EncodeToBase64String(signedMessage));
var token = "SharedAccessSignature sig=" + signature + "&se=" + expires_seconds + "&skn=" + SasKeyName + "&sr=" + targetUri;
return token;
}
public async Task SendNotificationMessage(string message)
{
try
{
// basic http client (if needed)
var httpClient = new HttpClient();
httpClient.MaxResponseContentBufferSize = 1024000;
var notificationPayload = "{\"aps\":{\"alert\":\"" + message + "\"}}";
var notificationHubUrl = $"{Endpoint}{HubName}/messages/{ApiVersion}";
var authToken = GetSaSToken(notificationHubUrl, 10);
var request = new HttpRequestMessage(HttpMethod.Post, notificationHubUrl);
//request.Headers.Add("Content-Type", "application/json;charset=utf-8");
request.Headers.Add("ServiceBusNotification-Format", "apple");
request.Headers.Add("ServiceBusNotification-Apns-Expiry", DateTime.UtcNow.AddYears(1).ToString("YYYY-MM-DDThh:mmTZD"));
request.Headers.Add("Authorization", authToken);
var requestBody = new StringContent(notificationPayload, Encoding.UTF8, "application/json");
request.Content = requestBody;
var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseContentRead);
}
catch (Exception ex)
{
Console.Error.WriteLine(#"ERROR - Sending Notification {0}", ex.Message);
}
}
}
Example of Connection String:
Endpoint=sb://company-name.servicebus.windows.net/;SharedAccessKeyName=DefaultFullSharedAccessSignature;SharedAccessKey=00000000000000011111111111111122222222222222
Environment and Assumptions:
Xamarin.iOS solution using C#
Using PCLCrypto library for encryption
I am attempting to recreate the solution demonstrated in an Example in Azure examples github repo but using Xamarin.iOS
The connection string is taken directly from Azure portal
The code for generating SaS token is adapted from Azure NotificationHub REST Api Documentation
Notification hub works, I am able to send a test push notification through the hub UI and i see it come in on the device
What am I missing here? I wasn't able to find much relevant documentation for this error online. Any help would be greatly appreciated.
Update with Fix:
The following 2 changes to the code above fixed the issue for me:
Changed
ApiVersion = "?api-version=2014-09-01";
to
ApiVersion = "?api-version=2016-07";
Changed
request.Headers.Add("ServiceBusNotification-Apns-Expiry", DateTime.UtcNow.AddYears(1).ToString("YYYY-MM-DDThh:mmTZD"));
to
request.Headers.Add("ServiceBusNotification-Apns-Expiry", DateTime.UtcNow.AddYears(1).ToString("yyyy-MM-ddTHH:mm:sszzz"));
The Api Version 2014-09-01 is not correct. Please use 2016-07 as the Api version and you should be good.
Thanks
Sohrab
I've figured out the issue(s):
+1 to Sohrab for pointing out the Api Version, I updated it to ApiVersion = "?api-version=2016-07";
There was an error in the ServiceBusNotification-Apns-Expiry header value format, the date was not being correctly formatted to string. Corrected format string is this ToString("yyyy-MM-ddTHH:mm:sszzz")
Can someone please provide an example of how to use Google.Apis.Storage.v1 for uploading files to google cloud storage in c#?
I found that this basic operation is not as straight forward as you might expect. Google's documentation about it's Storage API is lacking in information about using it in C# (or any other .NET language). Searching for 'how to upload file to google cloud storage in c#' didn't exactly help me, so here is my working solution with some comments:
Preparation:
You need to create OAuth2 account in your Google Developers Console - go to Project/APIs & auth/Credentials.
Copy Client ID & Client Secret to your code. You will also need your Project name.
Code (it assumes that you've added Google.Apis.Storage.v1 via NuGet):
First, you need to authorize your requests:
var clientSecrets = new ClientSecrets();
clientSecrets.ClientId = clientId;
clientSecrets.ClientSecret = clientSecret;
//there are different scopes, which you can find here https://cloud.google.com/storage/docs/authentication
var scopes = new[] {#"https://www.googleapis.com/auth/devstorage.full_control"};
var cts = new CancellationTokenSource();
var userCredential = await GoogleWebAuthorizationBroker.AuthorizeAsync(clientSecrets,scopes, "yourGoogle#email", cts.Token);
Sometimes you might also want to refresh authorization token via:
await userCredential.RefreshTokenAsync(cts.Token);
You also need to create Storage Service:
var service = new Google.Apis.Storage.v1.StorageService();
Now you can make requests to Google Storage API.
Let's start with creating a new bucket:
var newBucket = new Google.Apis.Storage.v1.Data.Bucket()
{
Name = "your-bucket-name-1"
};
var newBucketQuery = service.Buckets.Insert(newBucket, projectName);
newBucketQuery.OauthToken = userCredential.Result.Token.AccessToken;
//you probably want to wrap this into try..catch block
newBucketQuery.Execute();
And it's done. Now, you can send a request to get list of all of your buckets:
var bucketsQuery = service.Buckets.List(projectName);
bucketsQuery.OauthToken = userCredential.Result.Token.AccessToken;
var buckets = bucketsQuery.Execute();
Last part is uploading new file:
//enter bucket name to which you want to upload file
var bucketToUpload = buckets.Items.FirstOrDefault().Name;
var newObject = new Object()
{
Bucket = bucketToUpload,
Name = "some-file-"+new Random().Next(1,666)
};
FileStream fileStream = null;
try
{
var dir = Directory.GetCurrentDirectory();
var path = Path.Combine(dir, "test.png");
fileStream = new FileStream(path, FileMode.Open);
var uploadRequest = new Google.Apis.Storage.v1.ObjectsResource.InsertMediaUpload(service, newObject,
bucketToUpload,fileStream,"image/png");
uploadRequest.OauthToken = userCredential.Result.Token.AccessToken;
await uploadRequest.UploadAsync();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
if (fileStream != null)
{
fileStream.Dispose();
}
}
And bam! New file will be visible in you Google Developers Console inside of selected bucket.
You can use Google Cloud APIs without SDK in the following ways:
Required api-key.json file
Install package Google.Apis.Auth.OAuth2 in order to authorize the
HTTP web request
You can set the default configuration for your application in this
way
I did the same using .NET core web API and details are given below:
Url details:
"GoogleCloudStorageBaseUrl": "https://www.googleapis.com/upload/storage/v1/b/",
"GoogleSpeechBaseUrl": "https://speech.googleapis.com/v1/operations/",
"GoogleLongRunningRecognizeBaseUrl": "https://speech.googleapis.com/v1/speech:longrunningrecognize",
"GoogleCloudScope": "https://www.googleapis.com/auth/cloud-platform",
public void GetConfiguration()
{
// Set global configuration
bucketName = _configuration.GetValue<string>("BucketName");
googleCloudStorageBaseUrl = _configuration.GetValue<string>("GoogleCloudStorageBaseUrl");
googleSpeechBaseUrl = _configuration.GetValue<string>("GoogleSpeechBaseUrl");
googleLongRunningRecognizeBaseUrl = _configuration.GetValue<string>("GoogleLongRunningRecognizeBaseUrl");
// Set google cloud credentials
string googleApplicationCredentialsPath = _configuration.GetValue<string>("GoogleCloudCredentialPath");
using (Stream stream = new FileStream(googleApplicationCredentialsPath, FileMode.Open, FileAccess.Read))
googleCredential = GoogleCredential.FromStream(stream).CreateScoped(_configuration.GetValue<string>("GoogleCloudScope"));
}
Get Oauth token:
public string GetOAuthToken()
{
return googleCredential.UnderlyingCredential.GetAccessTokenForRequestAsync("https://accounts.google.com/o/oauth2/v2/auth", CancellationToken.None).Result;
}
To upload file to cloud bucket:
public async Task<string> UploadMediaToCloud(string filePath, string objectName = null)
{
string bearerToken = GetOAuthToken();
byte[] fileBytes = File.ReadAllBytes(filePath);
objectName = objectName ?? Path.GetFileName(filePath);
var baseUrl = new Uri(string.Format(googleCloudStorageBaseUrl + "" + bucketName + "/o?uploadType=media&name=" + objectName + ""));
using (WebClient client = new WebClient())
{
client.Headers.Add(HttpRequestHeader.Authorization, "Bearer " + bearerToken);
client.Headers.Add(HttpRequestHeader.ContentType, "application/octet-stream");
byte[] response = await Task.Run(() => client.UploadData(baseUrl, "POST", fileBytes));
string responseInString = Encoding.UTF8.GetString(response);
return responseInString;
}
}
In order to perform any action to the cloud API, just need to make a HttpClient get/post request as per the requirement.
Thanks
This is for Google.Cloud.Storage.V1 (not Google.Apis.Storage.v1), but appears to be a bit simpler to perform an upload now. I started with the Client libraries "Getting Started" instructions to create a service account and bucket, then experimented to find out how to upload an image.
The process I followed was:
Sign up for Google Cloud free trial
Create a new project in Google Cloud (remember the project name\ID for later)
Create a Project Owner service account - this will result in a json file being downloaded that contains the service account credentials. Remember where you put that file.
The getting started docs get you to add the path to the JSON credentials file into an environment variable called GOOGLE_APPLICATION_CREDENTIALS - I couldn't get this to work through the provided instructions. Turns out it is not required, as you can just read the JSON file into a string and pass it to the client constructor.
I created an empty WPF project as a starting point, and a single ViewModel to house the application logic.
Install the Google.Cloud.Storage.V1 nuget package and it should pull in all the dependencies it needs.
Onto the code.
MainWindow.xaml
<StackPanel>
<Button
Margin="50"
Height="50"
Content="BEGIN UPLOAD"
Click="OnButtonClick" />
<ContentControl
Content="{Binding Path=ProgressBar}" />
</StackPanel>
MainWindow.xaml.cs
public partial class MainWindow
{
readonly ViewModel _viewModel;
public MainWindow()
{
_viewModel = new ViewModel(Dispatcher);
DataContext = _viewModel;
InitializeComponent();
}
void OnButtonClick(object sender, RoutedEventArgs args)
{
_viewModel.UploadAsync().ConfigureAwait(false);
}
}
ViewModel.cs
public class ViewModel
{
readonly Dispatcher _dispatcher;
public ViewModel(Dispatcher dispatcher)
{
_dispatcher = dispatcher;
ProgressBar = new ProgressBar {Height=30};
}
public async Task UploadAsync()
{
// Google Cloud Platform project ID.
const string projectId = "project-id-goes-here";
// The name for the new bucket.
const string bucketName = projectId + "-test-bucket";
// Path to the file to upload
const string filePath = #"C:\path\to\image.jpg";
var newObject = new Google.Apis.Storage.v1.Data.Object
{
Bucket = bucketName,
Name = System.IO.Path.GetFileNameWithoutExtension(filePath),
ContentType = "image/jpeg"
};
// read the JSON credential file saved when you created the service account
var credential = Google.Apis.Auth.OAuth2.GoogleCredential.FromJson(System.IO.File.ReadAllText(
#"c:\path\to\service-account-credentials.json"));
// Instantiates a client.
using (var storageClient = Google.Cloud.Storage.V1.StorageClient.Create(credential))
{
try
{
// Creates the new bucket. Only required the first time.
// You can also create buckets through the GCP cloud console web interface
storageClient.CreateBucket(projectId, bucketName);
System.Windows.MessageBox.Show($"Bucket {bucketName} created.");
// Open the image file filestream
using (var fileStream = new System.IO.FileStream(filePath, System.IO.FileMode.Open))
{
ProgressBar.Maximum = fileStream.Length;
// set minimum chunksize just to see progress updating
var uploadObjectOptions = new Google.Cloud.Storage.V1.UploadObjectOptions
{
ChunkSize = Google.Cloud.Storage.V1.UploadObjectOptions.MinimumChunkSize
};
// Hook up the progress callback
var progressReporter = new Progress<Google.Apis.Upload.IUploadProgress>(OnUploadProgress);
await storageClient.UploadObjectAsync(
newObject,
fileStream,
uploadObjectOptions,
progress: progressReporter)
.ConfigureAwait(false);
}
}
catch (Google.GoogleApiException e)
when (e.Error.Code == 409)
{
// When creating the bucket - The bucket already exists. That's fine.
System.Windows.MessageBox.Show(e.Error.Message);
}
catch (Exception e)
{
// other exception
System.Windows.MessageBox.Show(e.Message);
}
}
}
// Called when progress updates
void OnUploadProgress(Google.Apis.Upload.IUploadProgress progress)
{
switch (progress.Status)
{
case Google.Apis.Upload.UploadStatus.Starting:
ProgressBar.Minimum = 0;
ProgressBar.Value = 0;
break;
case Google.Apis.Upload.UploadStatus.Completed:
ProgressBar.Value = ProgressBar.Maximum;
System.Windows.MessageBox.Show("Upload completed");
break;
case Google.Apis.Upload.UploadStatus.Uploading:
UpdateProgressBar(progress.BytesSent);
break;
case Google.Apis.Upload.UploadStatus.Failed:
System.Windows.MessageBox.Show("Upload failed"
+ Environment.NewLine
+ progress.Exception);
break;
}
}
void UpdateProgressBar(long value)
{
_dispatcher.Invoke(() => { ProgressBar.Value = value; });
}
// probably better to expose progress value directly and bind to
// a ProgressBar in the XAML
public ProgressBar ProgressBar { get; }
}
Use of Google.Apis.Storage.v1 for uploading files using SDK to google cloud storage in c#:
Required api-key.json file
Install the package Google.Cloud.Storage.V1; and Google.Apis.Auth.OAuth2;
The code is given below to upload the file to the cloud
private string UploadFile(string localPath, string objectName = null)
{
string projectId = ((Google.Apis.Auth.OAuth2.ServiceAccountCredential)googleCredential.UnderlyingCredential).ProjectId;
try
{
// Creates the new bucket.
var objResult = storageClient.CreateBucket(projectId, bucketName);
if (!string.IsNullOrEmpty(objResult.Id))
{
// Upload file to google cloud server
using (var f = File.OpenRead(localPath))
{
objectName = objectName ?? Path.GetFileName(localPath);
var objFileUploadStatus1 = storageClient.UploadObject(bucketName, objectName, null, f);
}
}
}
catch (Google.GoogleApiException ex)
{
// Error code =409, means bucket already created/exist then upload file in the bucket
if (ex.Error.Code == 409)
{
// Upload file to google cloud server
using (var f = File.OpenRead(localPath))
{
objectName = objectName ?? Path.GetFileName(localPath);
var objFileUploadStatus2 = storageClient.UploadObject(bucketName, objectName, null, f);
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
return objectName;
}
To set the credentials
private bool SetStorageCredentials()
{
bool status = true;
try
{
if (File.Exists(credential_path))
{
Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS", credential_path);
using (Stream objStream = new FileStream(Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS"), FileMode.Open, FileAccess.Read))
googleCredential = GoogleCredential.FromStream(objStream);
// Instantiates a client.
storageClient = StorageClient.Create();
channel = new Grpc.Core.Channel(SpeechClient.DefaultEndpoint.Host, googleCredential.ToChannelCredentials());
}
else
{
DialogResult result = MessageBox.Show("File " + Path.GetFileName(credential_path) + " does not exist. Please provide the correct path.");
if (result == System.Windows.Forms.DialogResult.OK)
{
status = false;
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
status = false;
}
return status;
}
I used SDK in one of my window application. You can use the same code according to your needs/requirements.
You'll be happy to know it still works in 2016...
I was googling all over using fancy key words like "google gcp C# upload image", until I just plain asked the question: "How do I upload an image to google bucket using C#"... and here I am. I removed the .Result in the user credential, and this was the final edit that worked for me.
// ******
static string bucketForImage = ConfigurationManager.AppSettings["testStorageName"];
static string projectName = ConfigurationManager.AppSettings["GCPProjectName"];
string gcpPath = Path.Combine(Server.MapPath("~/Images/Gallery/"), uniqueGcpName + ext);
var clientSecrets = new ClientSecrets();
clientSecrets.ClientId = ConfigurationManager.AppSettings["GCPClientID"];
clientSecrets.ClientSecret = ConfigurationManager.AppSettings["GCPClientSc"];
var scopes = new[] { #"https://www.googleapis.com/auth/devstorage.full_control" };
var cts = new CancellationTokenSource();
var userCredential = await GoogleWebAuthorizationBroker.AuthorizeAsync(clientSecrets, scopes, ConfigurationManager.AppSettings["GCPAccountEmail"], cts.Token);
var service = new Google.Apis.Storage.v1.StorageService();
var bucketToUpload = bucketForImage;
var newObject = new Google.Apis.Storage.v1.Data.Object()
{
Bucket = bucketToUpload,
Name = bkFileName
};
FileStream fileStream = null;
try
{
fileStream = new FileStream(gcpPath, FileMode.Open);
var uploadRequest = new Google.Apis.Storage.v1.ObjectsResource.InsertMediaUpload(service, newObject,
bucketToUpload, fileStream, "image/"+ ext);
uploadRequest.OauthToken = userCredential.Token.AccessToken;
await uploadRequest.UploadAsync();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
if (fileStream != null)
{
fileStream.Dispose();
}
}
// ******
Here is the link to their official C# example of ".NET Bookshelf App" using Google Cloud storage.
https://cloud.google.com/dotnet/docs/getting-started/using-cloud-storage
Source on github:
https://github.com/GoogleCloudPlatform/getting-started-dotnet/blob/master/aspnet/3-binary-data/Services/ImageUploader.cs
https://github.com/GoogleCloudPlatform/getting-started-dotnet/tree/master/aspnet/3-binary-data
Nuget
https://www.nuget.org/packages/Google.Cloud.Storage.V1/
Here are 2 examples that helped me to upload files to a bucket in Google Cloud Storage with Google.Cloud.Storage.V1 (not Google.Apis.Storage.v1):
Upload files to Google cloud storage using c#
Uploading .csv Files to Google Cloud Storage using C# .Net
I got both working on a C# Console Application just for testing purposes.
#February 2021
string _projectId = "YOUR-PROJECT-ID-GCP"; //ProjectID also present in the json file
GoogleCredential _credential = GoogleCredential.FromFile("credential-cloud-file-123418c9e06c.json");
/// <summary>
/// UploadFile to GCS Bucket
/// </summary>
/// <param name="bucketName"></param>
/// <param name="localPath">my-local-path/my-file-name</param>
/// <param name="objectName">my-file-name</param>
public void UploadFile(string bucketName, string localPath, string objectName)
{
var storage = StorageClient.Create(_credential);
using var fileStream = File.OpenRead(localPath);
storage.UploadObject(bucketName, objectName, null, fileStream);
Console.WriteLine($"Uploaded {objectName}.");
}
You get the credentials JSON file from the google cloud portal where you create a bucket under your project..
Simple, with auth:
private void SaveFileToGoogleStorage(string path, string? fileName, string ext)
{
var filePath = Path.Combine(path, fileName + ext);
var gcCredentialsPath = Path.Combine(Environment.CurrentDirectory, "gc_sa_key.json");
Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS", gcCredentialsPath);
var gcsStorage = StorageClient.Create();
using var f = File.OpenRead(filePath);
var objectName = Path.GetFileName(filePath);
gcsStorage.UploadObject(_bucketName, objectName, null, f);
Console.WriteLine($"Uploaded {objectName}.");
}
I have written the code to create an AMI using the C# SDK but haven't been able to create the AMI with only the Root Volume. By default it creates the AMI with all the EBS volumes attached to the instance. E.g. If it has 4 volumes it would create an AMI with 4 snapshots associated to it whereas I only need the C:\drive (Root Drive) included. I know that you have to use BlockDeviceMapping to specify the volume but not sure about the implementation any help would be appreciated.
public static void CreateAMI(string InstanceID, string AMIName, string AMIDescription)
{
try
{
Console.WriteLine("Creating AMI for InstanceID" + InstanceID);
AmazonEC2Config config = new AmazonEC2Config();
config.ProxyHost = ConfigurationManager.AppSettings["PROXYHOST"];
config.ProxyPort = Convert.ToInt32(ConfigurationManager.AppSettings["PROXYPORT"])
config.ServiceURL = "https://ec2." + Program.options.Region + ".amazonaws.com";
AmazonEC2 ec2 = AWSClientFactory.CreateAmazonEC2Client(Program.options.AccessKey, Program.options.SecretKey, config);
CreateImageRequest rq = new CreateImageRequest();
rq.InstanceId = InstanceID;
rq.Name = AMIName;
rq.Description = AMIDescription;
rq.NoReboot = true;
/* BlockDeviceMapping BMapping = new BlockDeviceMapping();
BMapping.DeviceName = "/dev/sda1";
rq.BlockDeviceMapping.Add(BMapping); */
CreateImageResponse rs = ec2.CreateImage(rq);
string AMIid = rs.CreateImageResult.ImageId;
Console.WriteLine("AMI Created with AMIid: " + AMIid);
Console.ReadLine();
}
catch (Exception err)
{
Console.WriteLine(err.Message + "/n" + err.StackTrace);
}
}
I think you need to specif your other device(s) EBS property to Null and NoDevice to something to make them not apart of your AMI. Your code should looks something like this.
//Create Drive Mapping List
var blockDeviceMappingList = new List<BlockDeviceMapping>();
//Create Mappings
var blockDeviceMapping = new BlockDeviceMapping();
var blockDeviceMapping2 = new BlockDeviceMapping();
//Specif a mount point of the drive you want (root)
blockDeviceMapping.DeviceName = "/dev/sda1";
var ebsBlockDevice = new EbsBlockDevice();
//Set something other than null constructor or u get an error about EBS not set. Likely has to do with how they build the request to send to the server
ebsBlockDevice.VolumeType = VolumeType.Standard;
blockDeviceMapping.Ebs = ebsBlockDevice;
//Specif a mount point of the unwanted drive and set EBS to null and NoDevice
blockDeviceMapping2.DeviceName = "/dev/sdf";
blockDeviceMapping2.Ebs = null;
blockDeviceMapping2.NoDevice = string.Empty;
//Add the mappings to the list
blockDeviceMappingList.Add(blockDeviceMapping);
blockDeviceMappingList.Add(blockDeviceMapping2);
//Setup Request
createImageRequest.BlockDeviceMappings = blockDeviceMappingList;
=)