/// <summary> /// Retrieve a specific server by Id. /// </summary> /// <param name="serverId"> /// The Id of the server to retrieve. /// </param> /// <param name="cancellationToken"> /// An optional cancellation token that can be used to cancel the request. /// </param> /// <returns> /// A <see cref="Server"/> representing the server, or <c>null</c> if no server was found with the specified Id. /// </returns> public async Task <Server> GetServer(Guid serverId, CancellationToken cancellationToken = default(CancellationToken)) { Guid organizationId = await GetOrganizationId(); HttpRequest getServer = Requests.Server.GetServerById .WithTemplateParameters(new { organizationId, serverId }); using (HttpResponseMessage response = await _httpClient.GetAsync(getServer, cancellationToken)) { if (!response.IsSuccessStatusCode) { ApiResponseV2 apiResponse = await response.ReadContentAsApiResponseV2(); if (apiResponse.ResponseCode == ApiResponseCodeV2.ResourceNotFound) { return(null); } throw CloudControlException.FromApiV2Response(apiResponse, response.StatusCode); } return(await response.ReadContentAsAsync <Server>()); } }
/// <summary> /// Create a new server. /// </summary> /// <param name="deploymentConfiguration"> /// The configuration that the new server will be deployed with. /// </param> /// <param name="cancellationToken"> /// An optional cancellation token that can be used to cancel the request. /// </param> /// <returns> /// The Id of the new server. /// </returns> public async Task <Guid> CreateServer(ServerDeploymentConfiguration deploymentConfiguration, CancellationToken cancellationToken = default(CancellationToken)) { if (deploymentConfiguration == null) { throw new ArgumentNullException(nameof(deploymentConfiguration)); } Guid organizationId = await GetOrganizationId(); HttpRequest createServer = Requests.Server.CreateServer.WithTemplateParameter("organizationId", organizationId); using (HttpResponseMessage response = await _httpClient.PostAsJsonAsync(createServer, deploymentConfiguration, cancellationToken)) { ApiResponseV2 apiResponse = await response.ReadContentAsApiResponseV2(); if (apiResponse.ResponseCode != ApiResponseCodeV2.InProgress) { throw CloudControlException.FromApiV2Response(apiResponse, response.StatusCode); } string serverId = apiResponse.InfoMessages.GetByName("serverId"); if (String.IsNullOrWhiteSpace(serverId)) { throw new CloudControlException("Received an unexpected response from the CloudControl API (missing 'serverId' message)."); } return(new Guid(serverId)); } }
/// <summary> /// Asynchronously perform Cmdlet processing. /// </summary> /// <param name="cancellationToken"> /// A <see cref="CancellationToken"/> that can be used to cancel Cmdlet processing. /// </param> /// <returns> /// A <see cref="Task"/> representing the asynchronous operation. /// </returns> protected override async Task ProcessRecordAsync(CancellationToken cancellationToken) { CloudControlClient client = GetClient(); NetworkDomain networkDomain; switch (ParameterSetName) { case "From network domain": { networkDomain = NetworkDomain; break; } case "By Id": { networkDomain = await client.GetNetworkDomain(Id, cancellationToken); if (networkDomain == null) { WriteError( Errors.ResourceNotFoundById <NetworkDomain>(Id) ); return; } break; } default: { ThrowTerminatingError( Errors.UnrecognizedParameterSet(this) ); return; } } if (!ShouldProcess(target: $"network domain '{networkDomain.Id}' ('{networkDomain.Name}') in '{networkDomain.DatacenterId}'", action: "Destroy")) { return; } ApiResponseV2 apiResponse = await client.DeleteNetworkDomain(networkDomain.Id, cancellationToken); if (!apiResponse.IsSuccess()) { WriteError( Errors.CloudControlApi(client, apiResponse) ); } else { WriteObject(apiResponse); } }
/// <summary> /// Create a <see cref="CloudControlException"/> from a v2 API response. /// </summary> /// <param name="apiResponseV2"> /// The API response. /// </param> /// <returns> /// The configured <see cref="CloudControlException"/>. /// </returns> internal static CloudControlException FromApiV2Response(ApiResponseV2 apiResponseV2) { return(new CloudControlException($"The CloudControl API returned an error response: [{apiResponseV2.ResponseCode}] {apiResponseV2.Message}.") { ResponseCode = apiResponseV2.ResponseCode.ToString(), StatusCode = 0 }); }
/// <summary> /// Create a <see cref="CloudControlException"/> from a v2 API response. /// </summary> /// <param name="response"> /// The HTTP response message representing the . /// </param> /// <returns> /// The configured <see cref="CloudControlException"/>. /// </returns> public static async Task <CloudControlException> FromApiV2Response(HttpResponseMessage response) { if (response == null) { throw new ArgumentNullException(nameof(response)); } ApiResponseV2 apiResponse = await response.ReadContentAsApiResponseV2(); return(FromApiV2Response(apiResponse, response.StatusCode)); }
/// <summary> /// Create a new VLAN. /// </summary> /// <param name="name"> /// The name of the new VLAN. /// </param> /// <param name="description"> /// The description (if any) for the new VLAN. /// </param> /// <param name="networkDomainId"> /// The Id of the network domain in which the VLAN will be created. /// </param> /// <param name="privateIPv4BaseAddress"> /// The base address of the VLAN's private IPv4 network. /// </param> /// <param name="privateIPv4PrefixSize"> /// The optional size, in bits, of the VLAN's private IPv4 network prefix. /// /// Default is 24 (i.e. a class C network). /// </param> /// <param name="gatewayAddressing"> /// The gateway addressing style to use for the new VLAN. /// /// Default is <see cref="VlanGatewayAddressing.Low"/>. /// </param> /// <param name="cancellationToken"> /// An optional cancellation token that can be used to cancel the request. /// </param> /// <returns> /// The Id of the new VLAN. /// </returns> public async Task <Guid> CreateVlan(string name, string description, Guid networkDomainId, string privateIPv4BaseAddress, int privateIPv4PrefixSize = 24, VlanGatewayAddressing gatewayAddressing = VlanGatewayAddressing.Low, CancellationToken cancellationToken = default(CancellationToken)) { if (String.IsNullOrWhiteSpace(name)) { throw new ArgumentException("Must supply a valid name.", nameof(name)); } if (description == null) { description = ""; } if (networkDomainId == Guid.Empty) { throw new ArgumentException("Must supply a valid network domain Id.", nameof(networkDomainId)); } Guid organizationId = await GetOrganizationId(); HttpRequest request = Requests.Network.CreateVlan.WithTemplateParameter("organizationId", organizationId); HttpResponseMessage response = await _httpClient.PostAsJsonAsync(request, new CreateVlan { Name = name, Description = description, NetworkDomainId = networkDomainId, PrivateIPv4BaseAddress = privateIPv4BaseAddress, PrivateIPv4PrefixSize = privateIPv4PrefixSize, GatewayAddressing = gatewayAddressing }, cancellationToken ); using (response) { ApiResponseV2 apiResponse = await response.ReadContentAsApiResponseV2(); if (apiResponse.ResponseCode != ApiResponseCodeV2.InProgress) { throw CloudControlException.FromApiV2Response(apiResponse, response.StatusCode); } string vlanId = apiResponse.InfoMessages.GetByName("vlanId"); if (String.IsNullOrWhiteSpace(vlanId)) { throw new CloudControlException("Received an unexpected response from the CloudControl API (missing 'vlanId' message)."); } return(new Guid(vlanId)); } }
/// <summary> /// Create a new network domain. /// </summary> /// <param name="datacenterId"> /// The Id of the target datacenter (e.g. AU10, NA9). /// </param> /// <param name="name"> /// The name of the new network domain. /// </param> /// <param name="description"> /// The description (if any) for the new network domain. /// </param> /// <param name="type"> /// The network domain type. /// </param> /// <param name="cancellationToken"> /// An optional cancellation token that can be used to cancel the request. /// </param> /// <returns> /// The Id of the new network domain. /// </returns> public async Task <Guid> CreateNetworkDomain(string datacenterId, string name, string description, NetworkDomainType type, CancellationToken cancellationToken = default(CancellationToken)) { if (String.IsNullOrWhiteSpace(datacenterId)) { throw new ArgumentException("Must supply a valid datacenter Id.", nameof(datacenterId)); } if (String.IsNullOrWhiteSpace(name)) { throw new ArgumentException("Must supply a valid name.", nameof(name)); } if (description == null) { description = ""; } Guid organizationId = await GetOrganizationId(); HttpRequest request = Requests.Network.CreateNetworkDomain.WithTemplateParameter("organizationId", organizationId); HttpResponseMessage response = await _httpClient.PostAsJsonAsync(request, new CreateNetworkDomain { Name = name, Description = description, Type = type, DatacenterId = datacenterId }, cancellationToken ); using (response) { ApiResponseV2 apiResponse = await response.ReadContentAsApiResponseV2(); if (apiResponse.ResponseCode != ApiResponseCodeV2.InProgress) { throw CloudControlException.FromApiV2Response(apiResponse, response.StatusCode); } string networkDomainId = apiResponse.InfoMessages.GetByName("networkDomainId"); if (String.IsNullOrWhiteSpace(networkDomainId)) { throw new CloudControlException("Received an unexpected response from the CloudControl API (missing 'networkDomainId' message)."); } return(new Guid(networkDomainId)); } }
/// <summary> /// Create a new NAT rule. /// </summary> /// <param name="networkDomainId"> /// The Id of the network domain in which the NAT rule will be created. /// </param> /// <param name="internalIPAddress"> /// The internal IPv4 address targeted by the NAT rule. /// </param> /// <param name="externalIPAddress"> /// The external IPv4 address targeted by the NAT rule. /// </param> /// <param name="cancellationToken"> /// An optional cancellation token that can be used to cancel the request. /// </param> /// <returns> /// The Id of the new NAT rule. /// </returns> public async Task <Guid> CreateNatRule(Guid networkDomainId, string internalIPAddress, string externalIPAddress, CancellationToken cancellationToken = default(CancellationToken)) { if (networkDomainId == Guid.Empty) { throw new ArgumentException("Must supply a valid network domain Id.", nameof(networkDomainId)); } if (String.IsNullOrWhiteSpace(internalIPAddress)) { throw new ArgumentException("Must supply a internal IP address.", nameof(internalIPAddress)); } if (String.IsNullOrWhiteSpace(externalIPAddress)) { throw new ArgumentException("Must supply a internal IP address.", nameof(externalIPAddress)); } Guid organizationId = await GetOrganizationId(); HttpRequest createNatRule = Requests.Network.CreateNatRule.WithTemplateParameter("organizationId", organizationId); HttpResponseMessage response = await _httpClient.PostAsJsonAsync(createNatRule, new CreateNatRule { NetworkDomainId = networkDomainId, InternalIPAddress = internalIPAddress, ExternalIPAddress = externalIPAddress }, cancellationToken ); using (response) { ApiResponseV2 apiResponse = await response.ReadContentAsApiResponseV2(); if (apiResponse.ResponseCode != ApiResponseCodeV2.InProgress) { throw CloudControlException.FromApiV2Response(apiResponse, response.StatusCode); } string natRuleId = apiResponse.InfoMessages.GetByName("natRuleId"); if (String.IsNullOrWhiteSpace(natRuleId)) { throw new CloudControlException("Received an unexpected response from the CloudControl API (missing 'natRuleId' message)."); } return(new Guid(natRuleId)); } }
public void GetAppointmentTest() { var appointment = Builder <AppointmentResponse> .CreateNew().Build(); var expectedResponse = new ApiResponseV2 <AppointmentResponse>(appointment); _mockWebClient.Setup(c => c.DownloadString( It.Is <Uri>(uri => uri.ToString().EndsWith("v2.1/clinicians/appointments/" + appointment.AppointmentId)))) .Returns(JsonConvert.SerializeObject(expectedResponse)); var response = _api.GetAppointment(appointment.AppointmentId); AssertAppointments(expectedResponse.Data.First(), response.Data.First()); _mockWebClient.Verify(client => client.DownloadString( It.Is <Uri>(uri => uri.ToString().EndsWith("v2.1/clinicians/appointments/" + appointment.AppointmentId)))); }
/// <summary> /// Create a <see cref="CloudControlException"/> from a v2 API response. /// </summary> /// <param name="apiResponseV2"> /// The API response. /// </param> /// <param name="statusCode"> /// The HTTP status code. /// </param> /// <returns> /// The configured <see cref="CloudControlException"/>. /// </returns> public static CloudControlException FromApiV2Response(ApiResponseV2 apiResponseV2, HttpStatusCode statusCode) { if (apiResponseV2 == null) { throw new ArgumentNullException(nameof(apiResponseV2)); } if (statusCode == 0) { return(FromApiV2Response(apiResponseV2)); } return(new CloudControlException($"The CloudControl API returned an error response (HTTP {statusCode}): [{apiResponseV2.ResponseCode}] {apiResponseV2.Message}.") { ResponseCode = apiResponseV2.ResponseCode.ToString(), StatusCode = statusCode }); }
public void TestScheduleConsultation() { var response = new ApiResponseV2 <ScheduledConsultationResult>(new ScheduledConsultationResult { ConsultationId = 3 }); mockWebClient.Setup(c => c.UploadString(It.IsAny <Uri>(), "POST", It.IsAny <string>())) .Returns(JsonConvert.SerializeObject(response)); var result = api.ScheduleEncounter(encounterData); Assert.AreEqual(response.Data.First().ConsultationId, result.ConsultationId); mockWebClient.Verify(client => client.UploadString( It.Is <Uri>(uri => uri.ToString().Contains("v2/admin/schedule/consultations")), httpPost, JsonConvert.SerializeObject(encounterData))); }
/// <summary> /// Create an <see cref="ErrorRecord"/> representing an error from the CloudControl API. /// </summary> /// <param name="client"> /// The CloudControl API client. /// </param> /// <param name="apiResponse"> /// The API response from CloudControl. /// </param> /// <returns> /// The configured <see cref="ErrorRecord"/>. /// </returns> public static ErrorRecord CloudControlApi(CloudControlClient client, ApiResponseV2 apiResponse) { if (client == null) { throw new ArgumentNullException(nameof(client)); } if (apiResponse == null) { throw new ArgumentNullException(nameof(apiResponse)); } return(new ErrorRecord( exception: CloudControlException.FromApiV2Response(apiResponse, statusCode: 0), errorId: $"CloudControl.API.{apiResponse.ResponseCode}", errorCategory: ErrorCategory.NotSpecified, targetObject: client.BaseAddress?.AbsoluteUri ?? "Unknown" )); }
public void UpdateAppointmentTest() { var response = Builder <AppointmentResponse> .CreateNew().Build(); var appointment = Builder <AppointmentApiRequest> .CreateNew().Build(); var request = Builder <AppointmentApiRequest> .CreateNew().Build(); var expectedResponse = new ApiResponseV2 <AppointmentResponse>(response); _mockWebClient.Setup(c => c.UploadString(It.IsAny <Uri>(), "PUT", It.IsAny <string>())) .Returns(JsonConvert.SerializeObject(expectedResponse)); var appointmentId = expectedResponse.Data.First().AppointmentId; var actual = _api.UpdateAppointment(appointmentId, request); AssertAppointments(expectedResponse.Data.First(), actual.Data.First()); _mockWebClient.Verify(client => client.UploadString( It.Is <Uri>(uri => uri.ToString().EndsWith("v2.1/clinicians/appointments/" + appointmentId)), "PUT", JsonConvert.SerializeObject(appointment))); }
public void TestResendOnboardingEmail() { var request = new EmailUserRequest { HospitalId = 126, Email = "*****@*****.**" }; var expectedResponse = new ApiResponseV2 <string>(request.Email); string token; var mockWebClient = TokenandWebClientSetup(out token); mockWebClient.Setup(x => x.UploadString(new Uri(BaseUri, "v2/patients/single-trip-registration/resend-onboarding-email"), "POST", JsonConvert.SerializeObject(request))) .Returns(JsonConvert.SerializeObject(expectedResponse)); var api = new PatientProfileApi(Settings.Default.BaseUrl, null, Settings.Default.ApiDeveloperId, Settings.Default.ApiKey, mockWebClient.Object); var response = api.ResendOnboardingEmail(request); Assert.NotNull(response); Assert.AreEqual(request.Email, response.Data.First()); }
/// <summary> /// Asynchronously perform Cmdlet processing. /// </summary> /// <param name="cancellationToken"> /// A <see cref="CancellationToken"/> that can be used to cancel Cmdlet processing. /// </param> /// <returns> /// A <see cref="Task"/> representing the asynchronous operation. /// </returns> protected override async Task ProcessRecordAsync(CancellationToken cancellationToken) { CloudControlClient client = GetClient(); Vlan vlan; switch (ParameterSetName) { case "From VLAN": { vlan = VLAN; break; } case "By Id": { vlan = await client.GetVlan(Id, cancellationToken); if (vlan == null) { WriteError( Errors.ResourceNotFoundById <Vlan>(Id) ); return; } break; } default: { ThrowTerminatingError( Errors.UnrecognizedParameterSet(this) ); return; } } if (!ShouldProcess(target: $"VLAN '{vlan.Id}' ('{vlan.Name}') in '{vlan.NetworkDomain.Name}'", action: "Edit")) { return; } ApiResponseV2 editResponse = await client.EditVlan(vlan, cancellationToken); if (!editResponse.IsSuccess()) { WriteError( Errors.CloudControlApi(client, editResponse) ); return; } Vlan updatedVlan = await client.GetVlan(vlan.Id, cancellationToken); if (updatedVlan == null) { WriteError( Errors.ResourceNotFoundById <Vlan>(vlan.Id) ); return; } WriteObject(updatedVlan); }
/// <summary> /// Asynchronously perform Cmdlet processing. /// </summary> /// <param name="cancellationToken"> /// A <see cref="CancellationToken"/> that can be used to cancel Cmdlet processing. /// </param> /// <returns> /// A <see cref="Task"/> representing the asynchronous operation. /// </returns> protected override async Task ProcessRecordAsync(CancellationToken cancellationToken) { CloudControlClient client = GetClient(); Vlan vlan; switch (ParameterSetName) { case "From VLAN": { vlan = VLAN; break; } case "By Id": { vlan = await client.GetVlan(Id, cancellationToken); if (vlan == null) { WriteError( Errors.ResourceNotFoundById <Vlan>(Id) ); return; } break; } default: { ThrowTerminatingError( Errors.UnrecognizedParameterSet(this) ); return; } } IPAddress baseAddress = IPAddress.Parse(vlan.PrivateIPv4Range.Address); IPAddress existingStartAddress, existingEndAddress; baseAddress.CalculateIPv4NetworkAddresses(vlan.PrivateIPv4Range.PrefixSize, out existingStartAddress, out existingEndAddress ); string existingNetwork = $"{baseAddress}/{vlan.PrivateIPv4Range.PrefixSize} ({existingStartAddress}-{existingEndAddress})"; IPAddress targetStartAddress, targetEndAddress; baseAddress.CalculateIPv4NetworkAddresses(IPv4PrefixSize, out targetStartAddress, out targetEndAddress ); string targetNetwork = $"{baseAddress}/{IPv4PrefixSize} ({targetStartAddress}-{targetEndAddress})"; if (IPv4PrefixSize >= vlan.PrivateIPv4Range.PrefixSize) { InvalidParameter(nameof(IPv4PrefixSize), $"Cannot expand VLAN network from {existingNetwork} to {targetNetwork}. To expand the VLAN's IPv4 network, reduce its IPv4 prefix size." ); return; } WriteVerbose( $"Expanding VLAN '{vlan.Name}' (in network domain '{vlan.NetworkDomain.Name}') from {existingNetwork} to {targetNetwork}." ); if (!ShouldProcess(target: $"'{vlan.Name}' ('{vlan.Id}') in '{vlan.NetworkDomain.Name}' (from {existingNetwork} to {targetNetwork}).", action: "Expand")) { return; } WriteVerbose("Initiating expansion of VLAN..."); ApiResponseV2 editResponse = await client.ExpandVlan(vlan.Id, IPv4PrefixSize, cancellationToken); if (!editResponse.IsSuccess()) { WriteError( Errors.CloudControlApi(client, editResponse) ); return; } WriteVerbose("VLAN expansion initiated."); Vlan updatedVlan = await client.GetVlan(vlan.Id, cancellationToken); if (updatedVlan == null) { WriteError( Errors.ResourceNotFoundById <Vlan>(vlan.Id) ); return; } WriteObject(updatedVlan); }