I'm trying to programmatically start up GCE instances from the C#/REST API (ie not using gcloud or the console). These instances must have values (identifying who started them, so will be different for each instance) passed to them during start-up, which will then get passed to the various applications running within. The obvious way of adding environment variables to the GCE request doesn't appear to be possible, so how does one provide dynamic configuration?
My current code for creating the instances which works fine:
public void CreateInstance(string name)
{
var credentials = GoogleCredential.GetApplicationDefault().CreateScoped(ComputeService.Scope.Compute);
var service = new ComputeService(new BaseClientService.Initializer
{
HttpClientInitializer = credentials,
ApplicationName = "Spin-up"
});
var spec = new Google.Apis.Compute.v1.Data.Instance
{
Name = name
};
var instanceTemplate = service.InstanceTemplates.Get(GCloudConfig.ProjectName, GCloudConfig.TemplateName).Execute();
var insertRequest = service.Instances.Insert(spec, GCloudConfig.ProjectName, GCloudConfig.Region);
insertRequest.SourceInstanceTemplate = instanceTemplate.SelfLink;
insertRequest.Execute();
}
You might use the API for Compute Engine Method: instances.start or instances.stop to trigger the start or stop of VM Instances with C# code requests.
Additional information about these API methods are described in documents: instances.start. and instances.stop.
Related
Microsoft Dynamics CRM 2015.
I test Asp.Net Core controller's action. When I create new Lead record some plugin generates new Guid for lead.new_master_id field (it's type is string). Therefore after creating I retrive the record to get it's generated new_master_id value. How can I emulate this plugin behaviour through Fake Xrm Easy?
var fakedContext = new XrmFakedContext();
fakedContext.ProxyTypesAssembly = typeof(Lead).Assembly;
var entities = new Entity[]
{
// is empty array
};
fakedContext.Initialize(entities);
var orgService = fakedContext.GetOrganizationService();
var lead = new Lead { FirstName = "James", LastName = "Bond" };
var leadId = orgService.Create(lead);
var masterId = orgService.Retrieve(Lead.EntityLogicalName, leadId,
new Microsoft.Xrm.Sdk.Query.ColumnSet(Lead.Fields.new_master_id))
.ToEntity<Lead>().new_master_id;
In v1.x of FakeXrmEasy you'll need to enable PipelineSimulation and register the plugin steps you would like to be fired on Create manually by registering their steps.
fakedContext.UsePipelineSimulation = true;
Once enabled, you'll need to enable the necessary steps via calling RegisterPluginStep. In your example you'll need to at least register something along the lines of:
fakedContext.RegisterPluginStep<LeadPlugin>("Create", ProcessingStepStage.Preoperation);
Where LeadPlugin would be the name of your plugin that generates the new_master_id property.
Keep in mind v1.x is limited in that it supports pipeline simulation for basic CRUD requests only.
Later versions (2.x and/or 3.x) come with a brand new middleware implementation allowing registering plugin steps for any message. Soon we'll be implementing automatic registration of plugin steps based on an actual environment and/or custom attributes.
Here's an example using the new middleware
public class FakeXrmEasyTestsBase
{
protected readonly IXrmFakedContext _context;
protected readonly IOrganizationServiceAsync2 _service;
public FakeXrmEasyTestsBase()
{
_context = MiddlewareBuilder
.New()
.AddCrud()
.AddFakeMessageExecutors()
.AddPipelineSimulation()
.UsePipelineSimulation()
.UseCrud()
.UseMessages()
.Build();
_service = _context.GetAsyncOrganizationService2();
}
}
You can find more info on the QuickStart guide here
Disclaimer: I'm the author of FakeXrmEasy :)
We're trying to use the REST API of Administration Service to manage the Configuration Manager
(What is the administration service in Configuration Manager?)
We have successfully queried entities of different types and executed some custom static methods (i.e. MoveMembers Method on SMS_ObjectContainerItem). It's all mostly blind shots as there is barely any documentation, but those basic functionalities seem to work fine.
Now we have hit the wall, trying to add collection rules to a SMS_Collection (existing or new). This was normally done calling the AddMembershipRule on the instance itself, that was previously fetched by e.g. WqlConnectionManager or some other proxy. However, this is clearly a no-go on a plain object fetched from the REST service.
We have tried to use the wmi OData service (by a generated proxy) as it clearly offers similar functionality, but this ends up with a "Not supported exception":
var savedCollection = Proxy.SMS_Collection.Where(c => c.CollectionID == result.CollectionID).FirstOrDefault();
savedCollection.AddMembershipRule(inclusionRule);
Proxy.UpdateObject(savedCollection);
Proxy.SaveChanges(); //EXCEPTION
I have tried running POST request in numerous ways, using urls like:
SMS_Collection.AddMembershipRule?CollectionID=DV000037 -> 404
SMS_Collection/DV000037/AddMembershipRule -> 404
SMS_Collection.DV000037.AddMembershipRule -> 404
SMS_Collection/DV000037.AddMembershipRule -> treated it as post to SMS_Collection/DV000037, and therefore triggers an update
or just
SMS_Collection.AddMembershipRule with collectionID as param
As for the request body I've used (or just the AddCollectionMembershipRuleRequestRule):
public class AddCollectionMembershipRuleRequest
{
public AddCollectionMembershipRuleRequestRule CollectionRule { get; set; }
}
public class AddCollectionMembershipRuleRequestRule
{
public string RuleName { get; set; }
public string IncludeCollectionID { get; set; }
}
I have also tried to Post an existing or new collection, with CollectionRules prefilled, but this ends up with an exception complaining about IncludeCollectionID not being part of CollectionRule (base class) - looks like validation being too strict and not dealing well with the inheritance.
var collectionRequest = new ECMCollectionCreationRequest()
{
Name = collectionName,
CollectionType = 2,
RefreshType = 4,
LimitToCollectionID = DefaultLimitingCollectionID,
CollectionRules = new List<SMS_CollectionRule>()
{
new SMS_CollectionRuleIncludeCollection()
{
RuleName = "MembershipRule",
IncludeCollectionID = "DV100020"
}
}
};
Stil, no luck with any of those. Do you have any idea if such a scenario (modification of CollectionRules) is even supported with the Rest /OData service? If so, what would be the right way to achieve so?
It looks like this part is simply not supported at the moment. Looking at the code it seems that the service is not interpreting the arguments properly and therefore causing validation issues.
However, the same can be achieved, in a bit less clean and structured way, using ManagementScope and ManagementObject
var scope = new ManagementScope(siteAddress);
scope.Connect();
using (ManagementObject collection = new ManagementObject(scope, new ManagementPath($"SMS_Collection.CollectionID='{collectionID}'"), new ObjectGetOptions()))
{
if (collection == null)
throw new Exception($"Unable to find collection with ID '{collectionID}'");
collection.Get();
using (ManagementBaseObject inParams = collection.GetMethodParameters("AddMembershipRule"))
using (ManagementClass ruleClass = new ManagementClass(scope, new ManagementPath("SMS_CollectionRuleDirect"), new ObjectGetOptions()))
using (ManagementObject rule = ruleClass.CreateInstance())
{
rule["ResourceClassName"] = "SMS_R_System";
rule["ResourceID"] = ecmResourceID;
rule["RuleName"] = machineName;
inParams["collectionRule"] = rule;
collection.InvokeMethod("AddMembershipRule", inParams, null);
}
}
One can add and remove all the other rule types in similar way.
Another alternative is of course to use PowerShell. Sill, I hope that with one of the next iterations of the Administration Service, support of those methods will be added.
Similarly, there seems to be no way to add/remove application or package and import/export them, using the admin services or even in the way mentioned above.
$Rule="{'collectionRule':{`"#odata.type`": `"#AdminService.SMS_CollectionRuleDirect`", `"ResourceClassName`": `"SMS_R_System`", `"ResourceID`": $DeviceID,`"RuleName`": `"$MachineName`"}}"
$RuleCreated = (Invoke-RestMethod -Method Post -Uri "https://$($CMProvider)/AdminService/wmi/SMS_Collection('$CollectionID')/AdminService.AddMembershipRule" -Body $Rule -ContentType 'application/json' -Credential $Cred)
I have an issue making phone calls from the foreground service and this is my question about that.
As suggested in the comments of the question - I started testing the ConnectionService. I added BIND_TELECOM_CONNECTION_SERVICE permission to the manifest file.
Declared MyConnectionService class:
[Service(Permission= Manifest.Permission.BindTelecomConnectionService)]
public class MyConnectionService : ConnectionService
{
}
And then I run this code:
var telecomManager = (TelecomManager)GetSystemService(Context.TelecomService);
var phoneAccountHandle = new PhoneAccountHandle(
new ComponentName(this.PackageName, nameof(MyConnectionService)), "MyApp");
var builder = new PhoneAccount.Builder(phoneAccountHandle, "CustomAccount");
var phoneAccount = builder.Build();
telecomManager.RegisterPhoneAccount(phoneAccount);
The telecomManager.RegisterPhoneAccount(phoneAccount); gives me an exception:
Java.Lang.SecurityException: 'PhoneAccount connection service requires BIND_TELECOM_CONNECTION_SERVICE permission.'
Ok - it seems the permission is not granted. Testing it with ActivityCompat.CheckSelfPermission() - yes, it is not granted.
Making a permission request with ActivityCompat.RequestPermissions() - it is executed and that's it.
No permission request on the screen, not way to grant on the application permission page.
My question is - how to grant this kind of permission?
Environmet:
Android API Level 28
Testing on Google Pixel 2 XL phone running Android 10
Comments by SushiHangover helped a lot and pointed to the right direction. In order to make the solution work and avoid the exception, the ConnectionService should have proper name (fully qualified Java class name) and permission declaration. These values can be added either in the manifest file or by declaring the ServiceAttribute in the code:
[Service(
Name = "com.sample.MyApp.MyConnectionService",
Permission = Manifest.Permission.BindTelecomConnectionService,
Enabled = true)]
public class MyConnectionService : ConnectionService
{
}
Secondly, the name of the service must be exact when creating ComponentName instance:
var telecomManager = (TelecomManager)GetSystemService(Context.TelecomService);
var phoneAccountHandle = new PhoneAccountHandle(
new ComponentName(this.PackageName, "com.sample.MyApp.MyConnectionService"),
"GateOpener");
var builder = new PhoneAccount.Builder(phoneAccountHandle, "CustomAccount");
var phoneAccount = builder.Build();
telecomManager.RegisterPhoneAccount(phoneAccount);
When programmatically creating a Cognito user pool and app client, if the app client is to have read/write access to attributes of the user pool, that access must be explicitly given. I have been able to do so successfully for custom attributes but built-in attributes always return an error of "Invalid write attributes specified while creating a client" or "Invalid read attributes specified while creating a client".
Documentation is ... both voluminous and difficult to find. I have yet to see an example of this or an actual bit of useful documentation on the CreateUserPoolClientRequest type that says anything about this other than things like "ReadAttributes is a list of strings that are the attributes that can be read".
Here is the code I'm using that always ends up with that error message and failure to create the app client. _client is an AmazonCognitoIdentityProviderClient properly instantiated and credentialed and running in a lambda function.
var request = new CreateUserPoolClientRequest { UserPoolId = userPoolId, ClientName = $"{name}AppClient" };
var builtInAttributes = new List<string>()
{
"address","birthdate","email","family name","gender","given name","locale","middle name","name","nickname","phone number", "picture","preferred username","profile","zoneinfo","updated at","website"
};
var readAttributes = new List<string>();
var writeAttributes = new List<string>();
readAttributes.InsertRange(0,builtInAttributes);
writeAttributes.InsertRange(0, builtInAttributes);
var attributeConfig = ConfigurationHelper.GetListFromSection("UserPoolCustomAttributes");
foreach (var attribute in attributeConfig)
{
readAttributes.Add($"custom:{attribute.Key}");
writeAttributes.Add($"custom:{attribute.Key}");
}
request.ReadAttributes = readAttributes;
request.WriteAttributes = writeAttributes;
var result = await _client.CreateUserPoolClientAsync(request, CancellationToken.None);
Any help is greatly appreciated.
Figured it out. Though I have yet to find it documented anywhere, default attributes with a space in the name in the ui need to have that space replaced with an underscore when using their name in the api.
Here i have a webjob function using servicebus triggers and outputs. I'd like to set a different configuration for output and input.
public static void OnPush(
[ServiceBusTrigger("%PushProcessor.InputTopicName%", "%PushProcessor.InputTopicSubscriptionName%", AccessRights.Listen)]
BrokeredMessage message,
[ServiceBus("%PushProcessor.OutputTopicName%", AccessRights.Send)]
out BrokeredMessage output
)
I see in latest api that one can control the job host with service bus extensions.
JobHostConfiguration config = new JobHostConfiguration
{
StorageConnectionString = ConfigHelpers.GetConfigValue("AzureWebJobsStorage"),
DashboardConnectionString = ConfigHelpers.GetConfigValue("AzureWebJobsDashboard"),
NameResolver = new ByAppSettingsNameResolver()
};
config.UseServiceBus(new ServiceBusConfiguration
{
MessageOptions = new OnMessageOptions {
MaxConcurrentCalls = 2,
AutoRenewTimeout = TimeSpan.FromMinutes(1),
AutoComplete = true,
},
ConnectionString = ConfigHelpers.GetConfigValue("InputServiceBusConnectionString"),
});
Unfortunately i see no control for the connection string for the output. I'd like a different connection string (different namespace/access rights) to be used for inputs versus outputs.
Perhaps the api can support registering named jobhostconfigurations to a jobhost, and referring to that name in the attributes for the trigger/output. Anyways if there is a way to do this let me know.
Yes, also in the latest beta1 release you'll see that there is now a ServiceBusAccountAttribute that you can apply along with the ServiceBusTrigger/ServiceBus attributes. For example:
public static void Test(
[ServiceBusTriggerAttribute("test"),
ServiceBusAccount("testaccount")] BrokeredMessage message)
{
. . .
}
We've done the same for all the other attribute types (Queue/Blob/Table) via StorageAccountAttribute. These account attributes can be applied at the class/method/parameter level. Please give this new feature a try and let us know how it works for you. Also, see the release notes for more details.