diff --git a/src/BinaryLane.Api/Http/BinaryLaneHttpExecutor.cs b/src/BinaryLane.Api/Http/BinaryLaneHttpExecutor.cs index 6e9065c..e152b3f 100644 --- a/src/BinaryLane.Api/Http/BinaryLaneHttpExecutor.cs +++ b/src/BinaryLane.Api/Http/BinaryLaneHttpExecutor.cs @@ -137,7 +137,7 @@ public sealed class BinaryLaneHttpExecutor : IBinaryLaneApiExecutor object? body = null, IReadOnlyDictionary? query = null, CancellationToken cancellationToken = default) => - (await SendAsync(new BinaryLaneRequest(new HttpMethod("PATCH"), path) { Body = body, Query = query }, cancellationToken) + (await SendAsync(new BinaryLaneRequest(BinaryLaneHttpMethods.Patch, path) { Body = body, Query = query }, cancellationToken) .ConfigureAwait(false)).Body; /// diff --git a/src/BinaryLane.Api/Http/BinaryLaneHttpMethods.cs b/src/BinaryLane.Api/Http/BinaryLaneHttpMethods.cs new file mode 100644 index 0000000..c59cfb9 --- /dev/null +++ b/src/BinaryLane.Api/Http/BinaryLaneHttpMethods.cs @@ -0,0 +1,9 @@ +using System.Net.Http; + +namespace BinaryLane.Api.V2.Http; + +/// HTTP methods required by the BinaryLane API beyond the framework's static set. +internal static class BinaryLaneHttpMethods +{ + internal static readonly HttpMethod Patch = new("PATCH"); +} diff --git a/src/BinaryLane.Api/Models/Accounts/AccountModels.cs b/src/BinaryLane.Api/Models/Accounts/AccountModels.cs new file mode 100644 index 0000000..ff6365a --- /dev/null +++ b/src/BinaryLane.Api/Models/Accounts/AccountModels.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace BinaryLane.Api.V2.Models; + +/// Information about the authenticated BinaryLane account. +public sealed class Account : BinaryLaneDto +{ + [JsonPropertyName("email")] + public string Email { get; init; } = string.Empty; + + [JsonPropertyName("email_verified")] + public bool EmailVerified { get; init; } + + [JsonPropertyName("two_factor_authentication_enabled")] + public bool TwoFactorAuthenticationEnabled { get; init; } + + /// Provider status, for example active. + [JsonPropertyName("status")] + public string Status { get; init; } = string.Empty; + + [JsonPropertyName("tax_code")] + public TaxCode TaxCode { get; init; } = new(); + + /// Provider payment-method values, for example credit-card. + [JsonPropertyName("configured_payment_methods")] + public IReadOnlyList ConfiguredPaymentMethods { get; init; } = Array.Empty(); + + [JsonPropertyName("additional_ipv4_limit")] + public int AdditionalIpv4Limit { get; init; } +} + +/// A tax code currently applicable to an account or invoice. +public sealed class TaxCode : BinaryLaneDto +{ + [JsonPropertyName("name")] + public string Name { get; init; } = string.Empty; + + /// Provider tax-code type, for example none or scalar. + [JsonPropertyName("type")] + public string Type { get; init; } = string.Empty; + + [JsonPropertyName("fixed_percent")] + public double? FixedPercent { get; init; } +} + +public sealed class AccountResponse : BinaryLaneDto +{ + [JsonPropertyName("account")] + public Account Account { get; init; } = new(); +} diff --git a/src/BinaryLane.Api/Models/Actions/ActionModels.cs b/src/BinaryLane.Api/Models/Actions/ActionModels.cs new file mode 100644 index 0000000..5a7f591 --- /dev/null +++ b/src/BinaryLane.Api/Models/Actions/ActionModels.cs @@ -0,0 +1,124 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace BinaryLane.Api.V2.Models; + +/// A provider action, which may still be in progress. +public sealed class BinaryLaneAction : BinaryLaneDto +{ + [JsonPropertyName("id")] + public long Id { get; init; } + + /// Provider status, for example in-progress, completed, or errored. + [JsonPropertyName("status")] + public string Status { get; init; } = string.Empty; + + [JsonPropertyName("type")] + public string Type { get; init; } = string.Empty; + + [JsonPropertyName("started_at")] + public DateTimeOffset StartedAt { get; init; } + + [JsonPropertyName("completed_at")] + public DateTimeOffset? CompletedAt { get; init; } + + /// Provider resource type, when the action is associated with one. + [JsonPropertyName("resource_type")] + public string? ResourceType { get; init; } + + [JsonPropertyName("resource_id")] + public long? ResourceId { get; init; } + + [JsonPropertyName("region")] + public Region? Region { get; init; } + + [JsonPropertyName("region_slug")] + public string? RegionSlug { get; init; } + + [JsonPropertyName("title")] + public string Title { get; init; } = string.Empty; + + [JsonPropertyName("reason")] + public string Reason { get; init; } = string.Empty; + + [JsonPropertyName("progress")] + public ActionProgress Progress { get; init; } = new(); + + [JsonPropertyName("result_data")] + public string? ResultData { get; init; } + + [JsonPropertyName("blocking_invoice_id")] + public long? BlockingInvoiceId { get; init; } + + [JsonPropertyName("user_interaction_required")] + public UserInteractionRequired? UserInteractionRequired { get; init; } +} + +/// Progress information for a long-running provider action. +public sealed class ActionProgress : BinaryLaneDto +{ + [JsonPropertyName("current_step_detail")] + public string? CurrentStepDetail { get; init; } + + [JsonPropertyName("percent_complete")] + public int PercentComplete { get; init; } + + [JsonPropertyName("current_step")] + public string? CurrentStep { get; init; } + + [JsonPropertyName("completed_steps")] + public IReadOnlyList CompletedSteps { get; init; } = Array.Empty(); +} + +/// A link to an action related to a completed request. +public sealed class ActionLink : BinaryLaneDto +{ + [JsonPropertyName("id")] + public long Id { get; init; } + + [JsonPropertyName("rel")] + public string Rel { get; init; } = string.Empty; + + [JsonPropertyName("href")] + public string Href { get; init; } = string.Empty; +} + +/// Indicates that an action needs an explicit user decision. +public sealed class UserInteractionRequired : BinaryLaneDto +{ + /// Provider interaction type, such as continue-after-ping-failure. + [JsonPropertyName("interaction_type")] + public string InteractionType { get; init; } = string.Empty; +} + +public sealed class ActionResponse : BinaryLaneDto +{ + [JsonPropertyName("action")] + public BinaryLaneAction Action { get; init; } = new(); +} + +public sealed class ActionsLinks : BinaryLaneDto +{ + [JsonPropertyName("actions")] + public IReadOnlyList Actions { get; init; } = Array.Empty(); +} + +public sealed class ActionsResponse : BinaryLaneDto +{ + [JsonPropertyName("meta")] + public PageMeta Meta { get; init; } = new(); + + [JsonPropertyName("links")] + public PageLinks? Links { get; init; } + + [JsonPropertyName("actions")] + public IReadOnlyList Actions { get; init; } = Array.Empty(); +} + +/// Allows or declines the interaction requested by an action. +public sealed class ProceedRequest : BinaryLaneRequestModel +{ + [JsonPropertyName("proceed")] + public bool Proceed { get; init; } +} diff --git a/src/BinaryLane.Api/Models/Billing/BillingModels.cs b/src/BinaryLane.Api/Models/Billing/BillingModels.cs new file mode 100644 index 0000000..e94d712 --- /dev/null +++ b/src/BinaryLane.Api/Models/Billing/BillingModels.cs @@ -0,0 +1,129 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace BinaryLane.Api.V2.Models; + +/// The current billing balance for the authenticated account. +public sealed class Balance : BinaryLaneDto +{ + [JsonPropertyName("unbilled_total")] + public double UnbilledTotal { get; init; } + + [JsonPropertyName("available_credit")] + public double AvailableCredit { get; init; } + + [JsonPropertyName("charges")] + public IReadOnlyList Charges { get; init; } = Array.Empty(); + + [JsonPropertyName("generated_at")] + public DateTimeOffset? GeneratedAt { get; init; } +} + +/// A charge included in a balance response. +public sealed class ChargeInformation : BinaryLaneDto +{ + [JsonPropertyName("created")] + public DateTimeOffset Created { get; init; } + + [JsonPropertyName("description")] + public string Description { get; init; } = string.Empty; + + [JsonPropertyName("total")] + public double Total { get; init; } + + [JsonPropertyName("ongoing")] + public bool Ongoing { get; init; } +} + +/// A BinaryLane invoice. +public sealed class Invoice : BinaryLaneDto +{ + [JsonPropertyName("invoice_id")] + public long InvoiceId { get; init; } + + [JsonPropertyName("reference")] + public string? Reference { get; init; } + + [JsonPropertyName("invoice_number")] + public string InvoiceNumber { get; init; } = string.Empty; + + [JsonPropertyName("amount")] + public double Amount { get; init; } + + [JsonPropertyName("tax_code")] + public TaxCode TaxCode { get; init; } = new(); + + [JsonPropertyName("tax")] + public double Tax { get; init; } + + [JsonPropertyName("created")] + public DateTimeOffset Created { get; init; } + + [JsonPropertyName("date_due")] + public DateTimeOffset DateDue { get; init; } + + [JsonPropertyName("date_overdue")] + public DateTimeOffset DateOverdue { get; init; } + + [JsonPropertyName("paid")] + public bool Paid { get; init; } + + [JsonPropertyName("refunded")] + public bool Refunded { get; init; } + + [JsonPropertyName("payment_failure_count")] + public int? PaymentFailureCount { get; init; } + + [JsonPropertyName("invoice_items")] + public IReadOnlyList InvoiceItems { get; init; } = Array.Empty(); + + [JsonPropertyName("invoice_download_url")] + public string? InvoiceDownloadUrl { get; init; } + + [JsonPropertyName("invoice_view_url")] + public string? InvoiceViewUrl { get; init; } +} + +/// A line item in a BinaryLane invoice. +public sealed class InvoiceLineItem : BinaryLaneDto +{ + [JsonPropertyName("name")] + public string Name { get; init; } = string.Empty; + + [JsonPropertyName("amount")] + public double Amount { get; init; } + + [JsonPropertyName("amount_includes_tax")] + public bool AmountIncludesTax { get; init; } +} + +public sealed class BalanceResponse : BinaryLaneDto +{ + [JsonPropertyName("balance")] + public Balance Balance { get; init; } = new(); +} + +public sealed class InvoiceResponse : BinaryLaneDto +{ + [JsonPropertyName("invoice")] + public Invoice Invoice { get; init; } = new(); +} + +public sealed class InvoicesResponse : BinaryLaneDto +{ + [JsonPropertyName("meta")] + public PageMeta Meta { get; init; } = new(); + + [JsonPropertyName("links")] + public PageLinks? Links { get; init; } + + [JsonPropertyName("invoices")] + public IReadOnlyList Invoices { get; init; } = Array.Empty(); +} + +public sealed class UnpaidFailedInvoicesResponse : BinaryLaneDto +{ + [JsonPropertyName("invoices")] + public IReadOnlyList Invoices { get; init; } = Array.Empty(); +} diff --git a/src/BinaryLane.Api/Models/BinaryLaneValues.cs b/src/BinaryLane.Api/Models/BinaryLaneValues.cs deleted file mode 100644 index ae26037..0000000 --- a/src/BinaryLane.Api/Models/BinaryLaneValues.cs +++ /dev/null @@ -1,275 +0,0 @@ -namespace BinaryLane.Api.V2.Models; - -/// -/// Known string values in the BinaryLane v2 contract. -/// -/// -/// The API remains a developer preview. Public DTOs use strings rather than -/// closed C# enums so an upstream value added after an SDK release remains -/// readable. These constants make documented values discoverable without -/// removing that forward compatibility. -/// -public static class BinaryLaneValues -{ - public static class AccountStatus - { - public const string Incomplete = "incomplete"; - public const string Active = "active"; - public const string Warning = "warning"; - public const string Locked = "locked"; - } - - public static class ActionStatus - { - public const string InProgress = "in-progress"; - public const string Completed = "completed"; - public const string Errored = "errored"; - } - - public static class ServerStatus - { - public const string New = "new"; - public const string Active = "active"; - public const string Archive = "archive"; - - // This unusual provider value is present in the 0.39.1 OpenAPI contract. - public const string ProviderFalse = "False"; - } - - public static class ResourceType - { - public const string Server = "server"; - public const string LoadBalancer = "load-balancer"; - public const string SshKey = "ssh-key"; - public const string Vpc = "vpc"; - public const string Image = "image"; - public const string RegisteredDomainName = "registered-domain-name"; - } - - public static class ImageType - { - public const string Custom = "custom"; - public const string Snapshot = "snapshot"; - public const string Backup = "backup"; - } - - public static class ImageStatus - { - public const string New = "NEW"; - public const string Available = "available"; - public const string Pending = "pending"; - public const string Deleted = "deleted"; - } - - public static class ImageQueryType - { - public const string Distribution = "distribution"; - public const string Backup = "backup"; - } - - public static class BackupSlot - { - public const string Daily = "daily"; - public const string Weekly = "weekly"; - public const string Monthly = "monthly"; - public const string Temporary = "temporary"; - } - - public static class BackupReplacementStrategy - { - public const string None = "none"; - public const string Specified = "specified"; - public const string Oldest = "oldest"; - public const string Newest = "newest"; - } - - public static class NetworkType - { - public const string Private = "private"; - public const string Public = "public"; - } - - public static class DomainRecordType - { - public const string A = "A"; - public const string Aaaa = "AAAA"; - public const string Caa = "CAA"; - public const string Cname = "CNAME"; - public const string Mx = "MX"; - public const string Ns = "NS"; - public const string Soa = "SOA"; - public const string Srv = "SRV"; - public const string Txt = "TXT"; - } - - public static class LoadBalancerStatus - { - public const string New = "new"; - public const string Active = "active"; - public const string Errored = "errored"; - } - - public static class LoadBalancerRuleProtocol - { - public const string Http = "http"; - public const string Https = "https"; - } - - public static class HealthCheckProtocol - { - public const string Http = "http"; - public const string Https = "https"; - public const string Both = "both"; - } - - public static class AdvancedFirewallRuleProtocol - { - public const string All = "all"; - public const string Icmp = "icmp"; - public const string Tcp = "tcp"; - public const string Udp = "udp"; - } - - public static class AdvancedFirewallRuleAction - { - public const string Drop = "drop"; - public const string Accept = "accept"; - } - - public static class PasswordRecoveryType - { - public const string Manual = "manual"; - public const string OfflineClear = "offline-clear"; - public const string OfflineChange = "offline-change"; - public const string OnlineChange = "online-change"; - } - - public static class DistributionFeature - { - public const string Ssh = "ssh"; - public const string RemoteDesktop = "remote-desktop"; - public const string UserData = "user-data"; - } - - public static class DataInterval - { - public const string FiveMinute = "five-minute"; - public const string HalfHour = "half-hour"; - public const string FourHour = "four-hour"; - public const string Day = "day"; - public const string Week = "week"; - public const string Month = "month"; - } - - public static class ThresholdAlertType - { - public const string Cpu = "cpu"; - public const string StorageRequests = "storage-requests"; - public const string NetworkIncoming = "network-incoming"; - public const string NetworkOutgoing = "network-outgoing"; - public const string DataTransferUsed = "data-transfer-used"; - public const string StorageUsed = "storage-used"; - public const string MemoryUsed = "memory-used"; - public const string LockedBackupSlots = "locked-backup-slots"; - } - - public static class PaymentMethod - { - public const string CreditCard = "credit-card"; - public const string Paypal = "paypal"; - } - - public static class TaxCodeType - { - public const string None = "none"; - public const string Scalar = "scalar"; - } - - public static class UserInteractionType - { - public const string ContinueAfterPingFailure = "continue-after-ping-failure"; - public const string AllowUncleanPowerOff = "allow-unclean-power-off"; - } - - public static class AdvancedFeature - { - public const string EmulatedHyperV = "emulated-hyperv"; - public const string EmulatedDevices = "emulated-devices"; - public const string NestedVirt = "nested-virt"; - public const string DriverDisk = "driver-disk"; - public const string UnsetUuid = "unset-uuid"; - public const string LocalRtc = "local-rtc"; - public const string EmulatedTpm = "emulated-tpm"; - public const string CloudInit = "cloud-init"; - public const string QemuGuestAgent = "qemu-guest-agent"; - public const string UefiBoot = "uefi-boot"; - } - - public static class VideoDevice - { - public const string CirrusLogic = "cirrus-logic"; - public const string Standard = "standard"; - public const string Virtio = "virtio"; - public const string VirtioWide = "virtio-wide"; - } - - public static class VmMachineType - { - public const string PcI440Fx1Point5 = "pc_i440fx_1point5"; - public const string PcI440Fx2Point11 = "pc_i440fx_2point11"; - public const string PcI440Fx4Point1 = "pc_i440fx_4point1"; - public const string PcI440Fx4Point2 = "pc_i440fx_4point2"; - public const string PcI440Fx5Point0 = "pc_i440fx_5point0"; - public const string PcI440Fx5Point1 = "pc_i440fx_5point1"; - public const string PcI440Fx7Point2 = "pc_i440fx_7point2"; - public const string PcI440Fx7Point2Point1 = "pc_i440fx_7point2point1"; - public const string PcI440Fx8Point2 = "pc_i440fx_8point2"; - } - - /// Discriminator values for payloads. - public static class ServerActionType - { - public const string AddDisk = "add_disk"; - public const string AttachBackup = "attach_backup"; - public const string ChangeAdvancedFeatures = "change_advanced_features"; - public const string ChangeAdvancedFirewallRules = "change_advanced_firewall_rules"; - public const string ChangeBackupSchedule = "change_backup_schedule"; - public const string ChangeIpv6 = "change_ipv6"; - public const string ChangeIpv6ReverseNameservers = "change_ipv6_reverse_nameservers"; - public const string ChangeKernel = "change_kernel"; - public const string ChangeManageOffsiteBackupCopies = "change_manage_offsite_backup_copies"; - public const string ChangeNetwork = "change_network"; - public const string ChangeOffsiteBackupLocation = "change_offsite_backup_location"; - public const string ChangePartner = "change_partner"; - public const string ChangePortBlocking = "change_port_blocking"; - public const string ChangeRegion = "change_region"; - public const string ChangeReverseName = "change_reverse_name"; - public const string ChangeSeparatePrivateNetworkInterface = "change_separate_private_network_interface"; - public const string ChangeSourceAndDestinationCheck = "change_source_and_destination_check"; - public const string ChangeThresholdAlerts = "change_threshold_alerts"; - public const string ChangeVpcIpv4 = "change_vpc_ipv4"; - public const string CloneUsingBackup = "clone_using_backup"; - public const string DeleteDisk = "delete_disk"; - public const string DetachBackup = "detach_backup"; - public const string DisableBackups = "disable_backups"; - public const string DisableSelinux = "disable_selinux"; - public const string EnableBackups = "enable_backups"; - public const string EnableIpv6 = "enable_ipv6"; - public const string IsRunning = "is_running"; - public const string PasswordReset = "password_reset"; - public const string Ping = "ping"; - public const string PowerCycle = "power_cycle"; - public const string PowerOff = "power_off"; - public const string PowerOn = "power_on"; - public const string Reboot = "reboot"; - public const string Rebuild = "rebuild"; - public const string Rename = "rename"; - public const string Resize = "resize"; - public const string ResizeDisk = "resize_disk"; - public const string Restore = "restore"; - public const string Shutdown = "shutdown"; - public const string TakeBackup = "take_backup"; - public const string Uncancel = "uncancel"; - public const string Uptime = "uptime"; - } -} diff --git a/src/BinaryLane.Api/Models/BinaryLaneDto.cs b/src/BinaryLane.Api/Models/Common/BinaryLaneDto.cs similarity index 100% rename from src/BinaryLane.Api/Models/BinaryLaneDto.cs rename to src/BinaryLane.Api/Models/Common/BinaryLaneDto.cs diff --git a/src/BinaryLane.Api/Models/Common/EnvelopeModels.cs b/src/BinaryLane.Api/Models/Common/EnvelopeModels.cs new file mode 100644 index 0000000..10c236b --- /dev/null +++ b/src/BinaryLane.Api/Models/Common/EnvelopeModels.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace BinaryLane.Api.V2.Models; + +/// Pagination metadata returned by BinaryLane list endpoints. +public sealed class PageMeta : BinaryLaneDto +{ + [JsonPropertyName("total")] + public int Total { get; init; } +} + +/// Pagination links returned by BinaryLane list endpoints. +public sealed class PageLinks : BinaryLaneDto +{ + [JsonPropertyName("pages")] + public PageNavigation Pages { get; init; } = new(); +} + +/// URLs for neighbouring pages in a BinaryLane list response. +public sealed class PageNavigation : BinaryLaneDto +{ + [JsonPropertyName("first")] + public string? First { get; init; } + + [JsonPropertyName("prev")] + public string? Previous { get; init; } + + [JsonPropertyName("next")] + public string? Next { get; init; } + + [JsonPropertyName("last")] + public string? Last { get; init; } +} + +/// An RFC 7807-style problem returned by BinaryLane. +public class ProblemDetails : BinaryLaneDto +{ + [JsonPropertyName("type")] + public string? Type { get; init; } + + [JsonPropertyName("title")] + public string? Title { get; init; } + + [JsonPropertyName("status")] + public int? Status { get; init; } + + [JsonPropertyName("detail")] + public string? Detail { get; init; } + + [JsonPropertyName("instance")] + public string? Instance { get; init; } +} + +/// A validation problem returned by BinaryLane. +public sealed class ValidationProblemDetails : ProblemDetails +{ + [JsonPropertyName("errors")] + public IReadOnlyDictionary>? Errors { get; init; } +} diff --git a/src/BinaryLane.Api/Models/IsExternalInit.cs b/src/BinaryLane.Api/Models/Compatibility/IsExternalInit.cs similarity index 100% rename from src/BinaryLane.Api/Models/IsExternalInit.cs rename to src/BinaryLane.Api/Models/Compatibility/IsExternalInit.cs diff --git a/src/BinaryLane.Api/Models/CoreModels.cs b/src/BinaryLane.Api/Models/CoreModels.cs deleted file mode 100644 index efbcd64..0000000 --- a/src/BinaryLane.Api/Models/CoreModels.cs +++ /dev/null @@ -1,615 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text.Json.Serialization; - -namespace BinaryLane.Api.V2.Models; - -/// Information about the authenticated BinaryLane account. -public sealed class Account : BinaryLaneDto -{ - [JsonPropertyName("email")] - public string Email { get; init; } = string.Empty; - - [JsonPropertyName("email_verified")] - public bool EmailVerified { get; init; } - - [JsonPropertyName("two_factor_authentication_enabled")] - public bool TwoFactorAuthenticationEnabled { get; init; } - - /// Provider status, for example active. - [JsonPropertyName("status")] - public string Status { get; init; } = string.Empty; - - [JsonPropertyName("tax_code")] - public TaxCode TaxCode { get; init; } = new(); - - /// Provider payment-method values, for example credit-card. - [JsonPropertyName("configured_payment_methods")] - public IReadOnlyList ConfiguredPaymentMethods { get; init; } = Array.Empty(); - - [JsonPropertyName("additional_ipv4_limit")] - public int AdditionalIpv4Limit { get; init; } -} - -/// A tax code currently applicable to an account or invoice. -public sealed class TaxCode : BinaryLaneDto -{ - [JsonPropertyName("name")] - public string Name { get; init; } = string.Empty; - - /// Provider tax-code type, for example none or scalar. - [JsonPropertyName("type")] - public string Type { get; init; } = string.Empty; - - [JsonPropertyName("fixed_percent")] - public double? FixedPercent { get; init; } -} - -/// A provider action, which may still be in progress. -public sealed class BinaryLaneAction : BinaryLaneDto -{ - [JsonPropertyName("id")] - public long Id { get; init; } - - /// Provider status, for example in-progress, completed, or errored. - [JsonPropertyName("status")] - public string Status { get; init; } = string.Empty; - - [JsonPropertyName("type")] - public string Type { get; init; } = string.Empty; - - [JsonPropertyName("started_at")] - public DateTimeOffset StartedAt { get; init; } - - [JsonPropertyName("completed_at")] - public DateTimeOffset? CompletedAt { get; init; } - - /// Provider resource type, when the action is associated with one. - [JsonPropertyName("resource_type")] - public string? ResourceType { get; init; } - - [JsonPropertyName("resource_id")] - public long? ResourceId { get; init; } - - [JsonPropertyName("region")] - public Region? Region { get; init; } - - [JsonPropertyName("region_slug")] - public string? RegionSlug { get; init; } - - [JsonPropertyName("title")] - public string Title { get; init; } = string.Empty; - - [JsonPropertyName("reason")] - public string Reason { get; init; } = string.Empty; - - [JsonPropertyName("progress")] - public ActionProgress Progress { get; init; } = new(); - - [JsonPropertyName("result_data")] - public string? ResultData { get; init; } - - [JsonPropertyName("blocking_invoice_id")] - public long? BlockingInvoiceId { get; init; } - - [JsonPropertyName("user_interaction_required")] - public UserInteractionRequired? UserInteractionRequired { get; init; } -} - -/// Progress information for a long-running provider action. -public sealed class ActionProgress : BinaryLaneDto -{ - [JsonPropertyName("current_step_detail")] - public string? CurrentStepDetail { get; init; } - - [JsonPropertyName("percent_complete")] - public int PercentComplete { get; init; } - - [JsonPropertyName("current_step")] - public string? CurrentStep { get; init; } - - [JsonPropertyName("completed_steps")] - public IReadOnlyList CompletedSteps { get; init; } = Array.Empty(); -} - -/// A link to an action related to a completed request. -public sealed class ActionLink : BinaryLaneDto -{ - [JsonPropertyName("id")] - public long Id { get; init; } - - [JsonPropertyName("rel")] - public string Rel { get; init; } = string.Empty; - - [JsonPropertyName("href")] - public string Href { get; init; } = string.Empty; -} - -/// Indicates that an action needs an explicit user decision. -public sealed class UserInteractionRequired : BinaryLaneDto -{ - /// Provider interaction type, such as continue-after-ping-failure. - [JsonPropertyName("interaction_type")] - public string InteractionType { get; init; } = string.Empty; -} - -/// A BinaryLane region in which a resource can be created. -public sealed class Region : BinaryLaneDto -{ - [JsonPropertyName("slug")] - public string Slug { get; init; } = string.Empty; - - [JsonPropertyName("name")] - public string Name { get; init; } = string.Empty; - - [JsonPropertyName("sizes")] - public IReadOnlyList Sizes { get; init; } = Array.Empty(); - - [JsonPropertyName("available")] - public bool Available { get; init; } - - [JsonPropertyName("features")] - public IReadOnlyList Features { get; init; } = Array.Empty(); - - [JsonPropertyName("name_servers")] - public IReadOnlyList NameServers { get; init; } = Array.Empty(); -} - -/// A BinaryLane server. -public sealed class Server : BinaryLaneDto -{ - [JsonPropertyName("id")] - public long Id { get; init; } - - [JsonPropertyName("name")] - public string Name { get; init; } = string.Empty; - - [JsonPropertyName("memory")] - public int MemoryMegabytes { get; init; } - - [JsonPropertyName("vcpus")] - public int Vcpus { get; init; } - - [JsonPropertyName("disk")] - public int DiskGigabytes { get; init; } - - [JsonPropertyName("vpc_id")] - public long? VpcId { get; init; } - - [JsonPropertyName("created_at")] - public DateTimeOffset CreatedAt { get; init; } - - /// Provider server status, for example active. - [JsonPropertyName("status")] - public string Status { get; init; } = string.Empty; - - [JsonPropertyName("backup_ids")] - public IReadOnlyList BackupIds { get; init; } = Array.Empty(); - - [JsonPropertyName("features")] - public IReadOnlyList Features { get; init; } = Array.Empty(); - - [JsonPropertyName("region")] - public Region Region { get; init; } = new(); - - [JsonPropertyName("image")] - public Image Image { get; init; } = new(); - - [JsonPropertyName("size")] - public Size Size { get; init; } = new(); - - [JsonPropertyName("size_slug")] - public string SizeSlug { get; init; } = string.Empty; - - [JsonPropertyName("selected_size_options")] - public SelectedSizeOptions? SelectedSizeOptions { get; init; } - - [JsonPropertyName("networks")] - public ServerNetworks Networks { get; init; } = new(); - - [JsonPropertyName("kernel")] - public Kernel? Kernel { get; init; } - - [JsonPropertyName("next_backup_window")] - public BackupWindow? NextBackupWindow { get; init; } - - [JsonPropertyName("disks")] - public IReadOnlyList Disks { get; init; } = Array.Empty(); - - [JsonPropertyName("backup_settings")] - public BackupSettings BackupSettings { get; init; } = new(); - - [JsonPropertyName("cancelled_at")] - public DateTimeOffset? CancelledAt { get; init; } - - [JsonPropertyName("failover_ips")] - public IReadOnlyList FailoverIps { get; init; } = Array.Empty(); - - [JsonPropertyName("host")] - public Host Host { get; init; } = new(); - - [JsonPropertyName("partner_id")] - public long? PartnerId { get; init; } - - [JsonPropertyName("password_change_supported")] - public bool PasswordChangeSupported { get; init; } - - [JsonPropertyName("permalink")] - public string? Permalink { get; init; } - - [JsonPropertyName("attached_backup")] - public AttachedBackup? AttachedBackup { get; init; } - - [JsonPropertyName("advanced_features")] - public AdvancedServerFeatures AdvancedFeatures { get; init; } = new(); - - [JsonPropertyName("is_under_maintenance")] - public bool? IsUnderMaintenance { get; init; } -} - -/// A server disk. -public sealed class Disk : BinaryLaneDto -{ - [JsonPropertyName("id")] - public long Id { get; init; } - - [JsonPropertyName("size_gigabytes")] - public double SizeGigabytes { get; init; } - - [JsonPropertyName("description")] - public string? Description { get; init; } - - [JsonPropertyName("primary")] - public bool Primary { get; init; } -} - -/// A server network assignment. -public sealed class ServerNetwork : BinaryLaneDto -{ - [JsonPropertyName("ip_address")] - public string IpAddress { get; init; } = string.Empty; - - /// May be represented by the provider as either a number or a string. - [JsonPropertyName("netmask")] - public object? Netmask { get; init; } - - [JsonPropertyName("gateway")] - public string? Gateway { get; init; } - - /// Provider network type, either public or private. - [JsonPropertyName("type")] - public string Type { get; init; } = string.Empty; - - [JsonPropertyName("reverse_name")] - public string? ReverseName { get; init; } - - [JsonPropertyName("nat_target")] - public string? NatTarget { get; init; } -} - -/// All IPv4/IPv6 network information associated with a server. -public sealed class ServerNetworks : BinaryLaneDto -{ - [JsonPropertyName("v4")] - public IReadOnlyList V4 { get; init; } = Array.Empty(); - - [JsonPropertyName("v6")] - public IReadOnlyList V6 { get; init; } = Array.Empty(); - - [JsonPropertyName("port_blocking")] - public bool PortBlocking { get; init; } - - [JsonPropertyName("separate_private_network_interface")] - public bool? SeparatePrivateNetworkInterface { get; init; } - - [JsonPropertyName("source_and_destination_check")] - public bool? SourceAndDestinationCheck { get; init; } - - [JsonPropertyName("recent_ddos")] - public bool RecentDdos { get; init; } - - [JsonPropertyName("ipv6_reverse_nameservers")] - public IReadOnlyList? Ipv6ReverseNameservers { get; init; } - - [JsonPropertyName("mac_address")] - public string MacAddress { get; init; } = string.Empty; -} - -/// A BinaryLane image, including operating-system and backup images. -public sealed class Image : BinaryLaneDto -{ - [JsonPropertyName("id")] - public long Id { get; init; } - - [JsonPropertyName("name")] - public string Name { get; init; } = string.Empty; - - /// Provider image type, for example custom, snapshot, or backup. - [JsonPropertyName("type")] - public string Type { get; init; } = string.Empty; - - [JsonPropertyName("distribution")] - public string? Distribution { get; init; } - - [JsonPropertyName("full_name")] - public string? FullName { get; init; } - - [JsonPropertyName("slug")] - public string? Slug { get; init; } - - [JsonPropertyName("public")] - public bool IsPublic { get; init; } - - [JsonPropertyName("regions")] - public IReadOnlyList Regions { get; init; } = Array.Empty(); - - [JsonPropertyName("created_at")] - public DateTimeOffset? CreatedAt { get; init; } - - [JsonPropertyName("min_disk_size")] - public int MinDiskSizeGigabytes { get; init; } - - [JsonPropertyName("size_gigabytes")] - public double SizeGigabytes { get; init; } - - [JsonPropertyName("description")] - public string? Description { get; init; } - - /// Provider image status, for example available. - [JsonPropertyName("status")] - public string Status { get; init; } = string.Empty; - - [JsonPropertyName("error_message")] - public string? ErrorMessage { get; init; } - - [JsonPropertyName("min_memory_megabytes")] - public int? MinMemoryMegabytes { get; init; } - - [JsonPropertyName("distribution_surcharges")] - public DistributionSurcharges? DistributionSurcharges { get; init; } - - [JsonPropertyName("distribution_info")] - public DistributionInfo DistributionInfo { get; init; } = new(); - - [JsonPropertyName("backup_info")] - public BackupInfo? BackupInfo { get; init; } -} - -/// Distribution-specific image installation capabilities. -public sealed class DistributionInfo : BinaryLaneDto -{ - [JsonPropertyName("image_id")] - public long ImageId { get; init; } - - /// Provider password recovery mode. - [JsonPropertyName("password_recovery")] - public string PasswordRecovery { get; init; } = string.Empty; - - [JsonPropertyName("remote_access_user")] - public string? RemoteAccessUser { get; init; } - - [JsonPropertyName("features")] - public IReadOnlyList Features { get; init; } = Array.Empty(); -} - -/// Additional provider charges for a distribution image. -public sealed class DistributionSurcharges : BinaryLaneDto -{ - [JsonPropertyName("surcharge_base_cost")] - public double? SurchargeBaseCost { get; init; } - - [JsonPropertyName("surcharge_per_memory_megabyte")] - public double? SurchargePerMemoryMegabyte { get; init; } - - [JsonPropertyName("surcharge_per_memory_max_megabytes")] - public int? SurchargePerMemoryMaxMegabytes { get; init; } - - [JsonPropertyName("surcharge_per_vcpu")] - public double? SurchargePerVcpu { get; init; } - - [JsonPropertyName("surcharge_min_vcpu")] - public int? SurchargeMinVcpu { get; init; } -} - -/// Backup-specific metadata for an image. -public sealed class BackupInfo : BinaryLaneDto -{ - /// Provider backup slot, such as daily or temporary. - [JsonPropertyName("type")] - public string Type { get; init; } = string.Empty; - - [JsonPropertyName("server_id")] - public long ServerId { get; init; } - - [JsonPropertyName("offsite")] - public bool Offsite { get; init; } - - [JsonPropertyName("locked")] - public bool Locked { get; init; } - - [JsonPropertyName("iso")] - public bool Iso { get; init; } - - [JsonPropertyName("backup_disks")] - public IReadOnlyList BackupDisks { get; init; } = Array.Empty(); -} - -/// A disk contained in a backup image. -public sealed class BackupDisk : BinaryLaneDto -{ - [JsonPropertyName("id")] - public long Id { get; init; } - - [JsonPropertyName("size_gigabytes")] - public double SizeGigabytes { get; init; } - - [JsonPropertyName("min_disk_size")] - public int MinDiskSizeGigabytes { get; init; } - - [JsonPropertyName("description")] - public string? Description { get; init; } -} - -/// A provider server size and its available customisation options. -public sealed class Size : BinaryLaneDto -{ - [JsonPropertyName("slug")] - public string Slug { get; init; } = string.Empty; - - [JsonPropertyName("description")] - public string? Description { get; init; } - - [JsonPropertyName("cpu_description")] - public string? CpuDescription { get; init; } - - [JsonPropertyName("storage_description")] - public string? StorageDescription { get; init; } - - [JsonPropertyName("size_type")] - public SizeType SizeType { get; init; } = new(); - - [JsonPropertyName("available")] - public bool Available { get; init; } - - [JsonPropertyName("regions")] - public IReadOnlyList Regions { get; init; } = Array.Empty(); - - [JsonPropertyName("regions_out_of_stock")] - public IReadOnlyList? RegionsOutOfStock { get; init; } - - [JsonPropertyName("price_monthly")] - public double PriceMonthly { get; init; } - - [JsonPropertyName("price_hourly")] - public double PriceHourly { get; init; } - - [JsonPropertyName("disk")] - public int DiskGigabytes { get; init; } - - [JsonPropertyName("memory")] - public int MemoryMegabytes { get; init; } - - [JsonPropertyName("transfer")] - public double TransferGigabytes { get; init; } - - [JsonPropertyName("excess_transfer_cost_per_gigabyte")] - public double ExcessTransferCostPerGigabyte { get; init; } - - [JsonPropertyName("vcpus")] - public int Vcpus { get; init; } - - [JsonPropertyName("vcpu_units")] - public string VcpuUnits { get; init; } = string.Empty; - - [JsonPropertyName("options")] - public SizeOptions Options { get; init; } = new(); -} - -/// The provider's category for a server size. -public sealed class SizeType : BinaryLaneDto -{ - [JsonPropertyName("slug")] - public string Slug { get; init; } = string.Empty; - - [JsonPropertyName("name")] - public string Name { get; init; } = string.Empty; - - [JsonPropertyName("description")] - public string? Description { get; init; } -} - -/// Configurable bounds and costs associated with a server size. -public sealed class SizeOptions : BinaryLaneDto -{ - [JsonPropertyName("disk_min")] - public int DiskMinGigabytes { get; init; } - - [JsonPropertyName("disk_max")] - public int DiskMaxGigabytes { get; init; } - - [JsonPropertyName("disk_cost_per_additional_gigabyte")] - public double DiskCostPerAdditionalGigabyte { get; init; } - - [JsonPropertyName("restricted_disk_values")] - public IReadOnlyList? RestrictedDiskValues { get; init; } - - [JsonPropertyName("memory_max")] - public int MemoryMaxMegabytes { get; init; } - - [JsonPropertyName("memory_cost_per_additional_megabyte")] - public double MemoryCostPerAdditionalMegabyte { get; init; } - - [JsonPropertyName("transfer_max")] - public double TransferMaxGigabytes { get; init; } - - [JsonPropertyName("transfer_cost_per_additional_gigabyte")] - public double TransferCostPerAdditionalGigabyte { get; init; } - - [JsonPropertyName("ipv4_addresses_max")] - public int Ipv4AddressesMax { get; init; } - - [JsonPropertyName("ipv4_addresses_cost_per_address")] - public double Ipv4AddressesCostPerAddress { get; init; } - - [JsonPropertyName("discount_for_no_public_ipv4")] - public double DiscountForNoPublicIpv4 { get; init; } - - [JsonPropertyName("daily_backups")] - public int DailyBackups { get; init; } - - [JsonPropertyName("weekly_backups")] - public int WeeklyBackups { get; init; } - - [JsonPropertyName("monthly_backups")] - public int MonthlyBackups { get; init; } - - [JsonPropertyName("backups_cost_per_backup_per_gigabyte")] - public double BackupsCostPerBackupPerGigabyte { get; init; } - - [JsonPropertyName("offsite_backups_cost_per_gigabyte")] - public double OffsiteBackupsCostPerGigabyte { get; init; } - - [JsonPropertyName("offsite_backup_frequency_cost")] - public OffsiteBackupFrequencyCost OffsiteBackupFrequencyCost { get; init; } = new(); -} - -/// The backup frequency costs published for a size. -public sealed class OffsiteBackupFrequencyCost : BinaryLaneDto -{ - [JsonPropertyName("daily_per_gigabyte")] - public double DailyPerGigabyte { get; init; } - - [JsonPropertyName("weekly_per_gigabyte")] - public double WeeklyPerGigabyte { get; init; } - - [JsonPropertyName("monthly_per_gigabyte")] - public double MonthlyPerGigabyte { get; init; } -} - -/// The options selected for an individual server. -public sealed class SelectedSizeOptions : BinaryLaneDto -{ - [JsonPropertyName("daily_backups")] - public int DailyBackups { get; init; } - - [JsonPropertyName("weekly_backups")] - public int WeeklyBackups { get; init; } - - [JsonPropertyName("monthly_backups")] - public int MonthlyBackups { get; init; } - - [JsonPropertyName("offsite_backups")] - public bool OffsiteBackups { get; init; } - - [JsonPropertyName("ipv4_addresses")] - public int Ipv4Addresses { get; init; } - - [JsonPropertyName("memory")] - public int MemoryMegabytes { get; init; } - - [JsonPropertyName("disk")] - public int DiskGigabytes { get; init; } - - [JsonPropertyName("transfer")] - public double TransferGigabytes { get; init; } -} diff --git a/src/BinaryLane.Api/Models/DataUsage/DataUsageModels.cs b/src/BinaryLane.Api/Models/DataUsage/DataUsageModels.cs new file mode 100644 index 0000000..be21e83 --- /dev/null +++ b/src/BinaryLane.Api/Models/DataUsage/DataUsageModels.cs @@ -0,0 +1,127 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace BinaryLane.Api.V2.Models; + +/// Current data-transfer use for a server. +public sealed class DataUsage : BinaryLaneDto +{ + [JsonPropertyName("server_id")] + public long ServerId { get; init; } + + [JsonPropertyName("expires")] + public DateTimeOffset Expires { get; init; } + + [JsonPropertyName("transfer_gigabytes")] + public long TransferGigabytes { get; init; } + + [JsonPropertyName("current_transfer_usage_gigabytes")] + public double CurrentTransferUsageGigabytes { get; init; } + + [JsonPropertyName("transfer_period_end")] + public DateTimeOffset TransferPeriodEnd { get; init; } +} + +/// A sample interval for server monitoring data. +public sealed class Period : BinaryLaneDto +{ + [JsonPropertyName("start")] + public DateTimeOffset Start { get; init; } + + [JsonPropertyName("end")] + public DateTimeOffset End { get; init; } + + /// Provider interval, such as five-minute or day. + [JsonPropertyName("data_interval")] + public string DataInterval { get; init; } = string.Empty; +} + +/// One monitoring aggregate sample. +public sealed class Sample : BinaryLaneDto +{ + [JsonPropertyName("cpu_usage_percent")] + public double CpuUsagePercent { get; init; } + + [JsonPropertyName("cpu_usage_detailed")] + public IReadOnlyList CpuUsageDetailed { get; init; } = Array.Empty(); + + [JsonPropertyName("memory_usage_bytes")] + public double MemoryUsageBytes { get; init; } + + [JsonPropertyName("network_incoming_kbps")] + public double NetworkIncomingKbps { get; init; } + + [JsonPropertyName("network_outgoing_kbps")] + public double NetworkOutgoingKbps { get; init; } + + [JsonPropertyName("storage_usage_megabytes")] + public double StorageUsageMegabytes { get; init; } + + [JsonPropertyName("storage_read_kbps")] + public double StorageReadKbps { get; init; } + + [JsonPropertyName("storage_write_kbps")] + public double StorageWriteKbps { get; init; } + + [JsonPropertyName("storage_read_requests_per_second")] + public double StorageReadRequestsPerSecond { get; init; } + + [JsonPropertyName("storage_write_requests_per_second")] + public double StorageWriteRequestsPerSecond { get; init; } +} + +/// A set of monitoring samples for a server. +public sealed class SampleSet : BinaryLaneDto +{ + [JsonPropertyName("server_id")] + public long ServerId { get; init; } + + [JsonPropertyName("period")] + public Period Period { get; init; } = new(); + + [JsonPropertyName("average")] + public Sample Average { get; init; } = new(); + + [JsonPropertyName("maximum_memory_megabytes")] + public double MaximumMemoryMegabytes { get; init; } + + [JsonPropertyName("maximum_storage_gigabytes")] + public double MaximumStorageGigabytes { get; init; } +} + +public sealed class DataUsageResponse : BinaryLaneDto +{ + [JsonPropertyName("data_usage")] + public DataUsage DataUsage { get; init; } = new(); +} + +public sealed class DataUsagesResponse : BinaryLaneDto +{ + [JsonPropertyName("meta")] + public PageMeta Meta { get; init; } = new(); + + [JsonPropertyName("links")] + public PageLinks? Links { get; init; } + + [JsonPropertyName("data_usages")] + public IReadOnlyList DataUsages { get; init; } = Array.Empty(); +} + +public sealed class SampleSetResponse : BinaryLaneDto +{ + [JsonPropertyName("sample_set")] + public SampleSet? SampleSet { get; init; } +} + +public sealed class SampleSetsResponse : BinaryLaneDto +{ + [JsonPropertyName("meta")] + public PageMeta Meta { get; init; } = new(); + + [JsonPropertyName("links")] + public PageLinks? Links { get; init; } + + [JsonPropertyName("sample_sets")] + public IReadOnlyList SampleSets { get; init; } = Array.Empty(); +} diff --git a/src/BinaryLane.Api/Models/Domains/DomainModels.cs b/src/BinaryLane.Api/Models/Domains/DomainModels.cs new file mode 100644 index 0000000..e32231a --- /dev/null +++ b/src/BinaryLane.Api/Models/Domains/DomainModels.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace BinaryLane.Api.V2.Models; + +/// A DNS domain managed through the BinaryLane API. +public sealed class Domain : BinaryLaneDto +{ + [JsonPropertyName("id")] + public long Id { get; init; } + + [JsonPropertyName("name")] + public string Name { get; init; } = string.Empty; + + [JsonPropertyName("current_nameservers")] + public IReadOnlyList CurrentNameservers { get; init; } = Array.Empty(); + + [JsonPropertyName("ttl")] + public int? Ttl { get; init; } + + [JsonPropertyName("zone_file")] + public string ZoneFile { get; init; } = string.Empty; +} + +/// A DNS record in a BinaryLane-managed domain. +public sealed class DomainRecord : BinaryLaneDto +{ + [JsonPropertyName("id")] + public long Id { get; init; } + + /// Provider DNS record type, such as A, AAAA, or TXT. + [JsonPropertyName("type")] + public string Type { get; init; } = string.Empty; + + [JsonPropertyName("name")] + public string Name { get; init; } = string.Empty; + + [JsonPropertyName("data")] + public string? Data { get; init; } + + [JsonPropertyName("priority")] + public int? Priority { get; init; } + + [JsonPropertyName("port")] + public int? Port { get; init; } + + [JsonPropertyName("ttl")] + public int Ttl { get; init; } + + [JsonPropertyName("weight")] + public int? Weight { get; init; } + + [JsonPropertyName("flags")] + public int? Flags { get; init; } + + [JsonPropertyName("tag")] + public string? Tag { get; init; } +} + +public sealed class LocalNameserversResponse : BinaryLaneDto +{ + [JsonPropertyName("local_nameservers")] + public IReadOnlyList LocalNameservers { get; init; } = Array.Empty(); +} + +public sealed class DomainResponse : BinaryLaneDto +{ + [JsonPropertyName("domain")] + public Domain Domain { get; init; } = new(); +} + +public sealed class DomainsResponse : BinaryLaneDto +{ + [JsonPropertyName("meta")] + public PageMeta Meta { get; init; } = new(); + + [JsonPropertyName("links")] + public PageLinks? Links { get; init; } + + [JsonPropertyName("domains")] + public IReadOnlyList Domains { get; init; } = Array.Empty(); +} + +public sealed class DomainRecordResponse : BinaryLaneDto +{ + [JsonPropertyName("domain_record")] + public DomainRecord DomainRecord { get; init; } = new(); +} + +public sealed class DomainRecordsResponse : BinaryLaneDto +{ + [JsonPropertyName("meta")] + public PageMeta Meta { get; init; } = new(); + + [JsonPropertyName("links")] + public PageLinks? Links { get; init; } + + [JsonPropertyName("domain_records")] + public IReadOnlyList DomainRecords { get; init; } = Array.Empty(); +} diff --git a/src/BinaryLane.Api/Models/Domains/DomainRequestModels.cs b/src/BinaryLane.Api/Models/Domains/DomainRequestModels.cs new file mode 100644 index 0000000..6293e76 --- /dev/null +++ b/src/BinaryLane.Api/Models/Domains/DomainRequestModels.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace BinaryLane.Api.V2.Models; + +/// Creates a DNS domain. +public sealed class DomainRequest : BinaryLaneRequestModel +{ + [JsonPropertyName("name")] + public string Name { get; init; } = string.Empty; + + [JsonPropertyName("ip_address")] + public string? IpAddress { get; init; } +} + +/// Requests refresh of the nameserver cache for domains. +public sealed class DomainRefreshRequest : BinaryLaneRequestModel +{ + [JsonPropertyName("domain_names")] + public IReadOnlyList DomainNames { get; init; } = Array.Empty(); +} + +/// Creates a DNS record. +public sealed class DomainRecordRequest : BinaryLaneRequestModel +{ + [JsonPropertyName("type")] + public string Type { get; init; } = string.Empty; + + [JsonPropertyName("name")] + public string Name { get; init; } = string.Empty; + + [JsonPropertyName("data")] + public string Data { get; init; } = string.Empty; + + [JsonPropertyName("priority")] + public int? Priority { get; init; } + + [JsonPropertyName("port")] + public int? Port { get; init; } + + [JsonPropertyName("ttl")] + public int? Ttl { get; init; } + + [JsonPropertyName("weight")] + public int? Weight { get; init; } + + [JsonPropertyName("flags")] + public int? Flags { get; init; } + + [JsonPropertyName("tag")] + public string? Tag { get; init; } +} + +/// Updates only the supplied parts of a DNS record. +public sealed class UpdateDomainRecordRequest : BinaryLaneRequestModel +{ + [JsonPropertyName("type")] + public string? Type { get; init; } + + [JsonPropertyName("name")] + public string? Name { get; init; } + + [JsonPropertyName("data")] + public string? Data { get; init; } + + [JsonPropertyName("priority")] + public int? Priority { get; init; } + + [JsonPropertyName("port")] + public int? Port { get; init; } + + [JsonPropertyName("ttl")] + public int? Ttl { get; init; } + + [JsonPropertyName("weight")] + public int? Weight { get; init; } + + [JsonPropertyName("flags")] + public int? Flags { get; init; } + + [JsonPropertyName("tag")] + public string? Tag { get; init; } +} diff --git a/src/BinaryLane.Api/Models/Images/ImageModels.cs b/src/BinaryLane.Api/Models/Images/ImageModels.cs new file mode 100644 index 0000000..5d8959b --- /dev/null +++ b/src/BinaryLane.Api/Models/Images/ImageModels.cs @@ -0,0 +1,190 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace BinaryLane.Api.V2.Models; + +/// A BinaryLane image, including operating-system and backup images. +public sealed class Image : BinaryLaneDto +{ + [JsonPropertyName("id")] + public long Id { get; init; } + + [JsonPropertyName("name")] + public string Name { get; init; } = string.Empty; + + /// Provider image type, for example custom, snapshot, or backup. + [JsonPropertyName("type")] + public string Type { get; init; } = string.Empty; + + [JsonPropertyName("distribution")] + public string? Distribution { get; init; } + + [JsonPropertyName("full_name")] + public string? FullName { get; init; } + + [JsonPropertyName("slug")] + public string? Slug { get; init; } + + [JsonPropertyName("public")] + public bool IsPublic { get; init; } + + [JsonPropertyName("regions")] + public IReadOnlyList Regions { get; init; } = Array.Empty(); + + [JsonPropertyName("created_at")] + public DateTimeOffset? CreatedAt { get; init; } + + [JsonPropertyName("min_disk_size")] + public int MinDiskSizeGigabytes { get; init; } + + [JsonPropertyName("size_gigabytes")] + public double SizeGigabytes { get; init; } + + [JsonPropertyName("description")] + public string? Description { get; init; } + + /// Provider image status, for example available. + [JsonPropertyName("status")] + public string Status { get; init; } = string.Empty; + + [JsonPropertyName("error_message")] + public string? ErrorMessage { get; init; } + + [JsonPropertyName("min_memory_megabytes")] + public int? MinMemoryMegabytes { get; init; } + + [JsonPropertyName("distribution_surcharges")] + public DistributionSurcharges? DistributionSurcharges { get; init; } + + [JsonPropertyName("distribution_info")] + public DistributionInfo DistributionInfo { get; init; } = new(); + + [JsonPropertyName("backup_info")] + public BackupInfo? BackupInfo { get; init; } +} + +/// Distribution-specific image installation capabilities. +public sealed class DistributionInfo : BinaryLaneDto +{ + [JsonPropertyName("image_id")] + public long ImageId { get; init; } + + /// Provider password recovery mode. + [JsonPropertyName("password_recovery")] + public string PasswordRecovery { get; init; } = string.Empty; + + [JsonPropertyName("remote_access_user")] + public string? RemoteAccessUser { get; init; } + + [JsonPropertyName("features")] + public IReadOnlyList Features { get; init; } = Array.Empty(); +} + +/// Additional provider charges for a distribution image. +public sealed class DistributionSurcharges : BinaryLaneDto +{ + [JsonPropertyName("surcharge_base_cost")] + public double? SurchargeBaseCost { get; init; } + + [JsonPropertyName("surcharge_per_memory_megabyte")] + public double? SurchargePerMemoryMegabyte { get; init; } + + [JsonPropertyName("surcharge_per_memory_max_megabytes")] + public int? SurchargePerMemoryMaxMegabytes { get; init; } + + [JsonPropertyName("surcharge_per_vcpu")] + public double? SurchargePerVcpu { get; init; } + + [JsonPropertyName("surcharge_min_vcpu")] + public int? SurchargeMinVcpu { get; init; } +} + +/// Backup-specific metadata for an image. +public sealed class BackupInfo : BinaryLaneDto +{ + /// Provider backup slot, such as daily or temporary. + [JsonPropertyName("type")] + public string Type { get; init; } = string.Empty; + + [JsonPropertyName("server_id")] + public long ServerId { get; init; } + + [JsonPropertyName("offsite")] + public bool Offsite { get; init; } + + [JsonPropertyName("locked")] + public bool Locked { get; init; } + + [JsonPropertyName("iso")] + public bool Iso { get; init; } + + [JsonPropertyName("backup_disks")] + public IReadOnlyList BackupDisks { get; init; } = Array.Empty(); +} + +/// A disk contained in a backup image. +public sealed class BackupDisk : BinaryLaneDto +{ + [JsonPropertyName("id")] + public long Id { get; init; } + + [JsonPropertyName("size_gigabytes")] + public double SizeGigabytes { get; init; } + + [JsonPropertyName("min_disk_size")] + public int MinDiskSizeGigabytes { get; init; } + + [JsonPropertyName("description")] + public string? Description { get; init; } +} + +/// A temporary download link for an image. +public sealed class ImageDownload : BinaryLaneDto +{ + [JsonPropertyName("id")] + public long Id { get; init; } + + [JsonPropertyName("expiry")] + public DateTimeOffset Expiry { get; init; } + + [JsonPropertyName("disks")] + public IReadOnlyList Disks { get; init; } = Array.Empty(); +} + +/// Download URLs for one disk in an image download. +public sealed class ImageDiskDownload : BinaryLaneDto +{ + [JsonPropertyName("id")] + public long Id { get; init; } + + [JsonPropertyName("compressed_url")] + public string CompressedUrl { get; init; } = string.Empty; + + [JsonPropertyName("raw_url")] + public string RawUrl { get; init; } = string.Empty; +} + +public sealed class ImageResponse : BinaryLaneDto +{ + [JsonPropertyName("image")] + public Image Image { get; init; } = new(); +} + +public sealed class ImagesResponse : BinaryLaneDto +{ + [JsonPropertyName("meta")] + public PageMeta Meta { get; init; } = new(); + + [JsonPropertyName("links")] + public PageLinks? Links { get; init; } + + [JsonPropertyName("images")] + public IReadOnlyList Images { get; init; } = Array.Empty(); +} + +public sealed class ImageDownloadResponse : BinaryLaneDto +{ + [JsonPropertyName("link")] + public ImageDownload Link { get; init; } = new(); +} diff --git a/src/BinaryLane.Api/Models/Images/ImageRequestModels.cs b/src/BinaryLane.Api/Models/Images/ImageRequestModels.cs new file mode 100644 index 0000000..f9c8cb5 --- /dev/null +++ b/src/BinaryLane.Api/Models/Images/ImageRequestModels.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace BinaryLane.Api.V2.Models; + +/// Changes mutable metadata on an image. +public sealed class ImageRequest : BinaryLaneRequestModel +{ + [JsonPropertyName("name")] + public string? Name { get; init; } + + [JsonPropertyName("locked")] + public bool? Locked { get; init; } +} + +/// Uploads an image into a backup slot. +public sealed class UploadImageRequest : BinaryLaneRequestModel +{ + /// Provider backup slot, required unless the replacement strategy is specified. + [JsonPropertyName("backup_type")] + public string? BackupType { get; init; } + + /// Provider replacement strategy: none, specified, oldest, or newest. + [JsonPropertyName("replacement_strategy")] + public string ReplacementStrategy { get; init; } = string.Empty; + + [JsonPropertyName("backup_id_to_replace")] + public long? BackupIdToReplace { get; init; } + + [JsonPropertyName("label")] + public string? Label { get; init; } + + [JsonPropertyName("url")] + public string Url { get; init; } = string.Empty; +} diff --git a/src/BinaryLane.Api/Models/LoadBalancers/LoadBalancerModels.cs b/src/BinaryLane.Api/Models/LoadBalancers/LoadBalancerModels.cs new file mode 100644 index 0000000..6dd2fb3 --- /dev/null +++ b/src/BinaryLane.Api/Models/LoadBalancers/LoadBalancerModels.cs @@ -0,0 +1,114 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace BinaryLane.Api.V2.Models; + +/// A BinaryLane load balancer. +public sealed class LoadBalancer : BinaryLaneDto +{ + [JsonPropertyName("id")] + public long Id { get; init; } + + [JsonPropertyName("name")] + public string Name { get; init; } = string.Empty; + + [JsonPropertyName("ip")] + public string Ip { get; init; } = string.Empty; + + /// Provider load balancer status, such as active. + [JsonPropertyName("status")] + public string Status { get; init; } = string.Empty; + + [JsonPropertyName("created_at")] + public DateTimeOffset CreatedAt { get; init; } + + [JsonPropertyName("forwarding_rules")] + public IReadOnlyList ForwardingRules { get; init; } = Array.Empty(); + + [JsonPropertyName("health_check")] + public HealthCheck HealthCheck { get; init; } = new(); + + [JsonPropertyName("region")] + public Region? Region { get; init; } + + [JsonPropertyName("server_ids")] + public IReadOnlyList ServerIds { get; init; } = Array.Empty(); +} + +/// A load-balancer forwarding rule. +public sealed class ForwardingRule : BinaryLaneDto +{ + /// Provider rule protocol, either http or https. + [JsonPropertyName("entry_protocol")] + public string EntryProtocol { get; init; } = string.Empty; +} + +/// A load-balancer health check. +public sealed class HealthCheck : BinaryLaneDto +{ + /// Provider health check protocol, such as http, https, or both. + [JsonPropertyName("protocol")] + public string Protocol { get; init; } = string.Empty; + + [JsonPropertyName("path")] + public string Path { get; init; } = string.Empty; +} + +/// A load-balancer configuration option available to the account. +public sealed class LoadBalancerAvailabilityOption : BinaryLaneDto +{ + [JsonPropertyName("regions")] + public IReadOnlyList? Regions { get; init; } + + [JsonPropertyName("anycast")] + public bool Anycast { get; init; } + + [JsonPropertyName("price_monthly")] + public double PriceMonthly { get; init; } + + [JsonPropertyName("price_hourly")] + public double PriceHourly { get; init; } +} + +public sealed class LoadBalancerResponse : BinaryLaneDto +{ + [JsonPropertyName("load_balancer")] + public LoadBalancer LoadBalancer { get; init; } = new(); +} + +public sealed class LoadBalancersResponse : BinaryLaneDto +{ + [JsonPropertyName("meta")] + public PageMeta Meta { get; init; } = new(); + + [JsonPropertyName("links")] + public PageLinks? Links { get; init; } + + [JsonPropertyName("load_balancers")] + public IReadOnlyList LoadBalancers { get; init; } = Array.Empty(); +} + +public sealed class CreateLoadBalancerResponse : BinaryLaneDto +{ + [JsonPropertyName("load_balancer")] + public LoadBalancer LoadBalancer { get; init; } = new(); + + [JsonPropertyName("links")] + public ActionsLinks Links { get; init; } = new(); +} + +public sealed class UpdateLoadBalancerResponse : BinaryLaneDto +{ + [JsonPropertyName("load_balancer")] + public LoadBalancer LoadBalancer { get; init; } = new(); + + [JsonPropertyName("links")] + public ActionsLinks? Links { get; init; } +} + +public sealed class LoadBalancerAvailabilityResponse : BinaryLaneDto +{ + [JsonPropertyName("load_balancer_availability_options")] + public IReadOnlyList LoadBalancerAvailabilityOptions { get; init; } = Array.Empty(); +} diff --git a/src/BinaryLane.Api/Models/LoadBalancers/LoadBalancerRequestModels.cs b/src/BinaryLane.Api/Models/LoadBalancers/LoadBalancerRequestModels.cs new file mode 100644 index 0000000..9acfd90 --- /dev/null +++ b/src/BinaryLane.Api/Models/LoadBalancers/LoadBalancerRequestModels.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace BinaryLane.Api.V2.Models; + +/// Creates a new load balancer. +public sealed class CreateLoadBalancerRequest : BinaryLaneRequestModel +{ + [JsonPropertyName("name")] + public string Name { get; init; } = string.Empty; + + [JsonPropertyName("forwarding_rules")] + public IReadOnlyList? ForwardingRules { get; init; } + + [JsonPropertyName("health_check")] + public HealthCheckRequest? HealthCheck { get; init; } + + [JsonPropertyName("server_ids")] + public IReadOnlyList? ServerIds { get; init; } + + [JsonPropertyName("region")] + public string? Region { get; init; } +} + +/// Updates a load balancer. +public sealed class UpdateLoadBalancerRequest : BinaryLaneRequestModel +{ + [JsonPropertyName("name")] + public string Name { get; init; } = string.Empty; + + [JsonPropertyName("forwarding_rules")] + public IReadOnlyList? ForwardingRules { get; init; } + + [JsonPropertyName("health_check")] + public HealthCheckRequest? HealthCheck { get; init; } + + [JsonPropertyName("server_ids")] + public IReadOnlyList? ServerIds { get; init; } +} + +/// A load-balancer forwarding rule supplied in a request. +public sealed class ForwardingRuleRequest : BinaryLaneRequestModel +{ + /// Either http or https. + [JsonPropertyName("entry_protocol")] + public string EntryProtocol { get; init; } = string.Empty; +} + +/// A collection of load-balancer forwarding rules. +public sealed class ForwardingRulesRequest : BinaryLaneRequestModel +{ + [JsonPropertyName("forwarding_rules")] + public IReadOnlyList ForwardingRules { get; init; } = Array.Empty(); +} + +/// A load-balancer health check supplied in a request. +public sealed class HealthCheckRequest : BinaryLaneRequestModel +{ + /// One of http, https, or both. + [JsonPropertyName("protocol")] + public string? Protocol { get; init; } + + [JsonPropertyName("path")] + public string? Path { get; init; } +} + +/// A collection of server IDs supplied to a load-balancer operation. +public sealed class ServerIdsRequest : BinaryLaneRequestModel +{ + [JsonPropertyName("server_ids")] + public IReadOnlyList ServerIds { get; init; } = Array.Empty(); +} diff --git a/src/BinaryLane.Api/Models/Regions/RegionModels.cs b/src/BinaryLane.Api/Models/Regions/RegionModels.cs new file mode 100644 index 0000000..f775b64 --- /dev/null +++ b/src/BinaryLane.Api/Models/Regions/RegionModels.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace BinaryLane.Api.V2.Models; + +/// A BinaryLane region in which a resource can be created. +public sealed class Region : BinaryLaneDto +{ + [JsonPropertyName("slug")] + public string Slug { get; init; } = string.Empty; + + [JsonPropertyName("name")] + public string Name { get; init; } = string.Empty; + + [JsonPropertyName("sizes")] + public IReadOnlyList Sizes { get; init; } = Array.Empty(); + + [JsonPropertyName("available")] + public bool Available { get; init; } + + [JsonPropertyName("features")] + public IReadOnlyList Features { get; init; } = Array.Empty(); + + [JsonPropertyName("name_servers")] + public IReadOnlyList NameServers { get; init; } = Array.Empty(); +} + +public sealed class RegionsResponse : BinaryLaneDto +{ + [JsonPropertyName("meta")] + public PageMeta Meta { get; init; } = new(); + + [JsonPropertyName("links")] + public PageLinks? Links { get; init; } + + [JsonPropertyName("regions")] + public IReadOnlyList Regions { get; init; } = Array.Empty(); +} diff --git a/src/BinaryLane.Api/Models/RequestModels.cs b/src/BinaryLane.Api/Models/RequestModels.cs deleted file mode 100644 index e1d03ec..0000000 --- a/src/BinaryLane.Api/Models/RequestModels.cs +++ /dev/null @@ -1,390 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text.Json.Serialization; - -namespace BinaryLane.Api.V2.Models; - -/// Options selected while creating or rebuilding a server image. -public sealed class ImageOptions : BinaryLaneRequestModel -{ - [JsonPropertyName("name")] - public string? Name { get; init; } - - /// Each identifier may be either an SSH key ID or a public-key fingerprint. - [JsonPropertyName("ssh_keys")] - public IReadOnlyList? SshKeys { get; init; } - - /// Do not log user-data; it can contain secrets. - [JsonPropertyName("user_data")] - public string? UserData { get; init; } - - /// Do not log this value. - [JsonPropertyName("password")] - public string? Password { get; init; } -} - -/// Customisable options for a server size. -public sealed class SizeOptionsRequest : BinaryLaneRequestModel -{ - [JsonPropertyName("daily_backups")] - public int? DailyBackups { get; init; } - - [JsonPropertyName("weekly_backups")] - public int? WeeklyBackups { get; init; } - - [JsonPropertyName("monthly_backups")] - public int? MonthlyBackups { get; init; } - - [JsonPropertyName("offsite_backups")] - public bool? OffsiteBackups { get; init; } - - [JsonPropertyName("ipv4_addresses")] - public int? Ipv4Addresses { get; init; } - - [JsonPropertyName("memory")] - public int? MemoryMegabytes { get; init; } - - [JsonPropertyName("disk")] - public int? DiskGigabytes { get; init; } - - [JsonPropertyName("transfer")] - public double? TransferGigabytes { get; init; } -} - -/// A requested software licence allocation. -public sealed class License : BinaryLaneRequestModel -{ - [JsonPropertyName("software_id")] - public long SoftwareId { get; init; } - - [JsonPropertyName("count")] - public int Count { get; init; } -} - -/// Creates a new BinaryLane server. -public sealed class CreateServerRequest : BinaryLaneRequestModel -{ - [JsonPropertyName("name")] - public string? Name { get; init; } - - [JsonPropertyName("backups")] - public bool? Backups { get; init; } - - [JsonPropertyName("ipv6")] - public bool? Ipv6 { get; init; } - - [JsonPropertyName("size")] - public string Size { get; init; } = string.Empty; - - /// An image ID or provider image slug. - [JsonPropertyName("image")] - public object Image { get; init; } = string.Empty; - - [JsonPropertyName("region")] - public string Region { get; init; } = string.Empty; - - [JsonPropertyName("vpc_id")] - public long? VpcId { get; init; } - - [JsonPropertyName("vpc_ipv4_address")] - public string? VpcIpv4Address { get; init; } - - /// Each entry may be an SSH key ID or fingerprint. - [JsonPropertyName("ssh_keys")] - public IReadOnlyList? SshKeys { get; init; } - - [JsonPropertyName("options")] - public SizeOptionsRequest? Options { get; init; } - - [JsonPropertyName("licenses")] - public IReadOnlyList? Licenses { get; init; } - - /// Do not log user-data; it may contain secrets. - [JsonPropertyName("user_data")] - public string? UserData { get; init; } - - [JsonPropertyName("port_blocking")] - public bool? PortBlocking { get; init; } - - [JsonPropertyName("separate_private_network_interface")] - public bool? SeparatePrivateNetworkInterface { get; init; } - - /// Do not log this value. - [JsonPropertyName("password")] - public string? Password { get; init; } -} - -/// Creates a new VPC. -public sealed class CreateVpcRequest : BinaryLaneRequestModel -{ - [JsonPropertyName("name")] - public string Name { get; init; } = string.Empty; - - [JsonPropertyName("route_entries")] - public IReadOnlyList? RouteEntries { get; init; } - - [JsonPropertyName("ip_range")] - public string? IpRange { get; init; } -} - -/// Replaces VPC configuration. Omitted properties are cleared by the provider. -public sealed class UpdateVpcRequest : BinaryLaneRequestModel -{ - [JsonPropertyName("name")] - public string Name { get; init; } = string.Empty; - - [JsonPropertyName("route_entries")] - public IReadOnlyList? RouteEntries { get; init; } -} - -/// Partially updates VPC configuration. -public sealed class PatchVpcRequest : BinaryLaneRequestModel -{ - [JsonPropertyName("name")] - public string? Name { get; init; } - - [JsonPropertyName("route_entries")] - public IReadOnlyList? RouteEntries { get; init; } -} - -/// A VPC route entry supplied in a create or update request. -public sealed class RouteEntryRequest : BinaryLaneRequestModel -{ - [JsonPropertyName("router")] - public string Router { get; init; } = string.Empty; - - [JsonPropertyName("destination")] - public string Destination { get; init; } = string.Empty; - - [JsonPropertyName("description")] - public string? Description { get; init; } -} - -/// Creates a new load balancer. -public sealed class CreateLoadBalancerRequest : BinaryLaneRequestModel -{ - [JsonPropertyName("name")] - public string Name { get; init; } = string.Empty; - - [JsonPropertyName("forwarding_rules")] - public IReadOnlyList? ForwardingRules { get; init; } - - [JsonPropertyName("health_check")] - public HealthCheckRequest? HealthCheck { get; init; } - - [JsonPropertyName("server_ids")] - public IReadOnlyList? ServerIds { get; init; } - - [JsonPropertyName("region")] - public string? Region { get; init; } -} - -/// Updates a load balancer. -public sealed class UpdateLoadBalancerRequest : BinaryLaneRequestModel -{ - [JsonPropertyName("name")] - public string Name { get; init; } = string.Empty; - - [JsonPropertyName("forwarding_rules")] - public IReadOnlyList? ForwardingRules { get; init; } - - [JsonPropertyName("health_check")] - public HealthCheckRequest? HealthCheck { get; init; } - - [JsonPropertyName("server_ids")] - public IReadOnlyList? ServerIds { get; init; } -} - -/// A load-balancer forwarding rule supplied in a request. -public sealed class ForwardingRuleRequest : BinaryLaneRequestModel -{ - /// Either http or https. - [JsonPropertyName("entry_protocol")] - public string EntryProtocol { get; init; } = string.Empty; -} - -/// A collection of load-balancer forwarding rules. -public sealed class ForwardingRulesRequest : BinaryLaneRequestModel -{ - [JsonPropertyName("forwarding_rules")] - public IReadOnlyList ForwardingRules { get; init; } = Array.Empty(); -} - -/// A load-balancer health check supplied in a request. -public sealed class HealthCheckRequest : BinaryLaneRequestModel -{ - /// One of http, https, or both. - [JsonPropertyName("protocol")] - public string? Protocol { get; init; } - - [JsonPropertyName("path")] - public string? Path { get; init; } -} - -/// A collection of server IDs supplied to a load-balancer operation. -public sealed class ServerIdsRequest : BinaryLaneRequestModel -{ - [JsonPropertyName("server_ids")] - public IReadOnlyList ServerIds { get; init; } = Array.Empty(); -} - -/// Creates a DNS domain. -public sealed class DomainRequest : BinaryLaneRequestModel -{ - [JsonPropertyName("name")] - public string Name { get; init; } = string.Empty; - - [JsonPropertyName("ip_address")] - public string? IpAddress { get; init; } -} - -/// Requests refresh of the nameserver cache for domains. -public sealed class DomainRefreshRequest : BinaryLaneRequestModel -{ - [JsonPropertyName("domain_names")] - public IReadOnlyList DomainNames { get; init; } = Array.Empty(); -} - -/// Creates a DNS record. -public sealed class DomainRecordRequest : BinaryLaneRequestModel -{ - [JsonPropertyName("type")] - public string Type { get; init; } = string.Empty; - - [JsonPropertyName("name")] - public string Name { get; init; } = string.Empty; - - [JsonPropertyName("data")] - public string Data { get; init; } = string.Empty; - - [JsonPropertyName("priority")] - public int? Priority { get; init; } - - [JsonPropertyName("port")] - public int? Port { get; init; } - - [JsonPropertyName("ttl")] - public int? Ttl { get; init; } - - [JsonPropertyName("weight")] - public int? Weight { get; init; } - - [JsonPropertyName("flags")] - public int? Flags { get; init; } - - [JsonPropertyName("tag")] - public string? Tag { get; init; } -} - -/// Updates only the supplied parts of a DNS record. -public sealed class UpdateDomainRecordRequest : BinaryLaneRequestModel -{ - [JsonPropertyName("type")] - public string? Type { get; init; } - - [JsonPropertyName("name")] - public string? Name { get; init; } - - [JsonPropertyName("data")] - public string? Data { get; init; } - - [JsonPropertyName("priority")] - public int? Priority { get; init; } - - [JsonPropertyName("port")] - public int? Port { get; init; } - - [JsonPropertyName("ttl")] - public int? Ttl { get; init; } - - [JsonPropertyName("weight")] - public int? Weight { get; init; } - - [JsonPropertyName("flags")] - public int? Flags { get; init; } - - [JsonPropertyName("tag")] - public string? Tag { get; init; } -} - -/// Creates an SSH key. -public sealed class SshKeyRequest : BinaryLaneRequestModel -{ - [JsonPropertyName("public_key")] - public string PublicKey { get; init; } = string.Empty; - - [JsonPropertyName("name")] - public string Name { get; init; } = string.Empty; - - [JsonPropertyName("default")] - public bool? IsDefault { get; init; } -} - -/// Updates an SSH key. -public sealed class UpdateSshKeyRequest : BinaryLaneRequestModel -{ - [JsonPropertyName("name")] - public string Name { get; init; } = string.Empty; - - [JsonPropertyName("default")] - public bool? IsDefault { get; init; } -} - -/// Changes mutable metadata on an image. -public sealed class ImageRequest : BinaryLaneRequestModel -{ - [JsonPropertyName("name")] - public string? Name { get; init; } - - [JsonPropertyName("locked")] - public bool? Locked { get; init; } -} - -/// Uploads an image into a backup slot. -public sealed class UploadImageRequest : BinaryLaneRequestModel -{ - /// Provider backup slot, required unless the replacement strategy is specified. - [JsonPropertyName("backup_type")] - public string? BackupType { get; init; } - - /// Provider replacement strategy: none, specified, oldest, or newest. - [JsonPropertyName("replacement_strategy")] - public string ReplacementStrategy { get; init; } = string.Empty; - - [JsonPropertyName("backup_id_to_replace")] - public long? BackupIdToReplace { get; init; } - - [JsonPropertyName("label")] - public string? Label { get; init; } - - [JsonPropertyName("url")] - public string Url { get; init; } = string.Empty; -} - -/// Updates the IPv6 reverse nameservers configured for the account. -public sealed class ReverseNameserversRequest : BinaryLaneRequestModel -{ - [JsonPropertyName("reverse_nameservers")] - public IReadOnlyList ReverseNameservers { get; init; } = Array.Empty(); -} - -/// Allows or declines the interaction requested by an action. -public sealed class ProceedRequest : BinaryLaneRequestModel -{ - [JsonPropertyName("proceed")] - public bool Proceed { get; init; } -} - -/// Updates threshold-alert configuration. -public sealed class ThresholdAlertRequest : BinaryLaneRequestModel -{ - /// Provider alert type. - [JsonPropertyName("alert_type")] - public string AlertType { get; init; } = string.Empty; - - [JsonPropertyName("enabled")] - public bool? Enabled { get; init; } - - [JsonPropertyName("value")] - public int? Value { get; init; } -} diff --git a/src/BinaryLane.Api/Models/ResourceModels.cs b/src/BinaryLane.Api/Models/ResourceModels.cs deleted file mode 100644 index e67e672..0000000 --- a/src/BinaryLane.Api/Models/ResourceModels.cs +++ /dev/null @@ -1,653 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text.Json.Serialization; - -namespace BinaryLane.Api.V2.Models; - -/// The current billing balance for the authenticated account. -public sealed class Balance : BinaryLaneDto -{ - [JsonPropertyName("unbilled_total")] - public double UnbilledTotal { get; init; } - - [JsonPropertyName("available_credit")] - public double AvailableCredit { get; init; } - - [JsonPropertyName("charges")] - public IReadOnlyList Charges { get; init; } = Array.Empty(); - - [JsonPropertyName("generated_at")] - public DateTimeOffset? GeneratedAt { get; init; } -} - -/// A charge included in a balance response. -public sealed class ChargeInformation : BinaryLaneDto -{ - [JsonPropertyName("created")] - public DateTimeOffset Created { get; init; } - - [JsonPropertyName("description")] - public string Description { get; init; } = string.Empty; - - [JsonPropertyName("total")] - public double Total { get; init; } - - [JsonPropertyName("ongoing")] - public bool Ongoing { get; init; } -} - -/// A BinaryLane invoice. -public sealed class Invoice : BinaryLaneDto -{ - [JsonPropertyName("invoice_id")] - public long InvoiceId { get; init; } - - [JsonPropertyName("reference")] - public string? Reference { get; init; } - - [JsonPropertyName("invoice_number")] - public string InvoiceNumber { get; init; } = string.Empty; - - [JsonPropertyName("amount")] - public double Amount { get; init; } - - [JsonPropertyName("tax_code")] - public TaxCode TaxCode { get; init; } = new(); - - [JsonPropertyName("tax")] - public double Tax { get; init; } - - [JsonPropertyName("created")] - public DateTimeOffset Created { get; init; } - - [JsonPropertyName("date_due")] - public DateTimeOffset DateDue { get; init; } - - [JsonPropertyName("date_overdue")] - public DateTimeOffset DateOverdue { get; init; } - - [JsonPropertyName("paid")] - public bool Paid { get; init; } - - [JsonPropertyName("refunded")] - public bool Refunded { get; init; } - - [JsonPropertyName("payment_failure_count")] - public int? PaymentFailureCount { get; init; } - - [JsonPropertyName("invoice_items")] - public IReadOnlyList InvoiceItems { get; init; } = Array.Empty(); - - [JsonPropertyName("invoice_download_url")] - public string? InvoiceDownloadUrl { get; init; } - - [JsonPropertyName("invoice_view_url")] - public string? InvoiceViewUrl { get; init; } -} - -/// A line item in a BinaryLane invoice. -public sealed class InvoiceLineItem : BinaryLaneDto -{ - [JsonPropertyName("name")] - public string Name { get; init; } = string.Empty; - - [JsonPropertyName("amount")] - public double Amount { get; init; } - - [JsonPropertyName("amount_includes_tax")] - public bool AmountIncludesTax { get; init; } -} - -/// Current data-transfer use for a server. -public sealed class DataUsage : BinaryLaneDto -{ - [JsonPropertyName("server_id")] - public long ServerId { get; init; } - - [JsonPropertyName("expires")] - public DateTimeOffset Expires { get; init; } - - [JsonPropertyName("transfer_gigabytes")] - public long TransferGigabytes { get; init; } - - [JsonPropertyName("current_transfer_usage_gigabytes")] - public double CurrentTransferUsageGigabytes { get; init; } - - [JsonPropertyName("transfer_period_end")] - public DateTimeOffset TransferPeriodEnd { get; init; } -} - -/// A DNS domain managed through the BinaryLane API. -public sealed class Domain : BinaryLaneDto -{ - [JsonPropertyName("id")] - public long Id { get; init; } - - [JsonPropertyName("name")] - public string Name { get; init; } = string.Empty; - - [JsonPropertyName("current_nameservers")] - public IReadOnlyList CurrentNameservers { get; init; } = Array.Empty(); - - [JsonPropertyName("ttl")] - public int? Ttl { get; init; } - - [JsonPropertyName("zone_file")] - public string ZoneFile { get; init; } = string.Empty; -} - -/// A DNS record in a BinaryLane-managed domain. -public sealed class DomainRecord : BinaryLaneDto -{ - [JsonPropertyName("id")] - public long Id { get; init; } - - /// Provider DNS record type, such as A, AAAA, or TXT. - [JsonPropertyName("type")] - public string Type { get; init; } = string.Empty; - - [JsonPropertyName("name")] - public string Name { get; init; } = string.Empty; - - [JsonPropertyName("data")] - public string? Data { get; init; } - - [JsonPropertyName("priority")] - public int? Priority { get; init; } - - [JsonPropertyName("port")] - public int? Port { get; init; } - - [JsonPropertyName("ttl")] - public int Ttl { get; init; } - - [JsonPropertyName("weight")] - public int? Weight { get; init; } - - [JsonPropertyName("flags")] - public int? Flags { get; init; } - - [JsonPropertyName("tag")] - public string? Tag { get; init; } -} - -/// A temporary download link for an image. -public sealed class ImageDownload : BinaryLaneDto -{ - [JsonPropertyName("id")] - public long Id { get; init; } - - [JsonPropertyName("expiry")] - public DateTimeOffset Expiry { get; init; } - - [JsonPropertyName("disks")] - public IReadOnlyList Disks { get; init; } = Array.Empty(); -} - -/// Download URLs for one disk in an image download. -public sealed class ImageDiskDownload : BinaryLaneDto -{ - [JsonPropertyName("id")] - public long Id { get; init; } - - [JsonPropertyName("compressed_url")] - public string CompressedUrl { get; init; } = string.Empty; - - [JsonPropertyName("raw_url")] - public string RawUrl { get; init; } = string.Empty; -} - -/// An SSH public key owned by the authenticated account. -public sealed class SshKey : BinaryLaneDto -{ - [JsonPropertyName("id")] - public long Id { get; init; } - - [JsonPropertyName("fingerprint")] - public string Fingerprint { get; init; } = string.Empty; - - [JsonPropertyName("public_key")] - public string PublicKey { get; init; } = string.Empty; - - [JsonPropertyName("name")] - public string? Name { get; init; } - - [JsonPropertyName("default")] - public bool IsDefault { get; init; } -} - -/// A BinaryLane load balancer. -public sealed class LoadBalancer : BinaryLaneDto -{ - [JsonPropertyName("id")] - public long Id { get; init; } - - [JsonPropertyName("name")] - public string Name { get; init; } = string.Empty; - - [JsonPropertyName("ip")] - public string Ip { get; init; } = string.Empty; - - /// Provider load balancer status, such as active. - [JsonPropertyName("status")] - public string Status { get; init; } = string.Empty; - - [JsonPropertyName("created_at")] - public DateTimeOffset CreatedAt { get; init; } - - [JsonPropertyName("forwarding_rules")] - public IReadOnlyList ForwardingRules { get; init; } = Array.Empty(); - - [JsonPropertyName("health_check")] - public HealthCheck HealthCheck { get; init; } = new(); - - [JsonPropertyName("region")] - public Region? Region { get; init; } - - [JsonPropertyName("server_ids")] - public IReadOnlyList ServerIds { get; init; } = Array.Empty(); -} - -/// A load-balancer forwarding rule. -public sealed class ForwardingRule : BinaryLaneDto -{ - /// Provider rule protocol, either http or https. - [JsonPropertyName("entry_protocol")] - public string EntryProtocol { get; init; } = string.Empty; -} - -/// A load-balancer health check. -public sealed class HealthCheck : BinaryLaneDto -{ - /// Provider health check protocol, such as http, https, or both. - [JsonPropertyName("protocol")] - public string Protocol { get; init; } = string.Empty; - - [JsonPropertyName("path")] - public string Path { get; init; } = string.Empty; -} - -/// A load-balancer configuration option available to the account. -public sealed class LoadBalancerAvailabilityOption : BinaryLaneDto -{ - [JsonPropertyName("regions")] - public IReadOnlyList? Regions { get; init; } - - [JsonPropertyName("anycast")] - public bool Anycast { get; init; } - - [JsonPropertyName("price_monthly")] - public double PriceMonthly { get; init; } - - [JsonPropertyName("price_hourly")] - public double PriceHourly { get; init; } -} - -/// A virtual private cloud. -public sealed class Vpc : BinaryLaneDto -{ - [JsonPropertyName("id")] - public long Id { get; init; } - - [JsonPropertyName("name")] - public string Name { get; init; } = string.Empty; - - [JsonPropertyName("ip_range")] - public string IpRange { get; init; } = string.Empty; - - [JsonPropertyName("route_entries")] - public IReadOnlyList RouteEntries { get; init; } = Array.Empty(); -} - -/// A route within a VPC. -public sealed class RouteEntry : BinaryLaneDto -{ - [JsonPropertyName("router")] - public string Router { get; init; } = string.Empty; - - [JsonPropertyName("destination")] - public string Destination { get; init; } = string.Empty; - - [JsonPropertyName("description")] - public string? Description { get; init; } -} - -/// A resource connected to a VPC. -public sealed class VpcMember : BinaryLaneDto -{ - [JsonPropertyName("name")] - public string Name { get; init; } = string.Empty; - - /// Provider resource type. - [JsonPropertyName("resource_type")] - public string ResourceType { get; init; } = string.Empty; - - /// The provider documents this as a string, unlike action resource identifiers. - [JsonPropertyName("resource_id")] - public string ResourceId { get; init; } = string.Empty; - - [JsonPropertyName("created_at")] - public DateTimeOffset? CreatedAt { get; init; } -} - -/// A scheduled backup window. -public sealed class BackupWindow : BinaryLaneDto -{ - [JsonPropertyName("start")] - public DateTimeOffset Start { get; init; } - - [JsonPropertyName("end")] - public DateTimeOffset End { get; init; } -} - -/// A server's configured backup schedule. -public sealed class BackupSettings : BinaryLaneDto -{ - [JsonPropertyName("backup_hour_of_day")] - public int BackupHourOfDay { get; init; } - - [JsonPropertyName("backup_day_of_week")] - public int BackupDayOfWeek { get; init; } - - [JsonPropertyName("backup_day_of_month")] - public int BackupDayOfMonth { get; init; } - - [JsonPropertyName("offsite_backup_settings")] - public OffsiteBackupSettings? OffsiteBackupSettings { get; init; } -} - -/// Offsite-backup configuration for a server. -public sealed class OffsiteBackupSettings : BinaryLaneDto -{ - [JsonPropertyName("use_custom_backup_location")] - public bool UseCustomBackupLocation { get; init; } - - [JsonPropertyName("offsite_backup_location")] - public string? OffsiteBackupLocation { get; init; } - - [JsonPropertyName("manage_offsite_copies")] - public bool? ManageOffsiteCopies { get; init; } -} - -/// The host backing a server. -public sealed class Host : BinaryLaneDto -{ - [JsonPropertyName("display_name")] - public string DisplayName { get; init; } = string.Empty; - - [JsonPropertyName("uptime_ms")] - public long? UptimeMilliseconds { get; init; } - - [JsonPropertyName("status_page")] - public string? StatusPage { get; init; } -} - -/// Metadata about a backup currently attached to a server. -public sealed class AttachedBackup : BinaryLaneDto -{ - [JsonPropertyName("id")] - public long Id { get; init; } - - [JsonPropertyName("disk_identifiers")] - public IReadOnlyList DiskIdentifiers { get; init; } = Array.Empty(); - - [JsonPropertyName("attached_at")] - public DateTimeOffset? AttachedAt { get; init; } - - [JsonPropertyName("attachment_expires")] - public DateTimeOffset? AttachmentExpires { get; init; } -} - -/// Advanced virtual-machine features configured for a server. -public sealed class AdvancedServerFeatures : BinaryLaneDto -{ - [JsonPropertyName("processor_model")] - public long? ProcessorModel { get; init; } - - /// Provider virtual machine type. - [JsonPropertyName("machine_type")] - public string? MachineType { get; init; } - - /// Provider virtual video device. - [JsonPropertyName("video_device")] - public string VideoDevice { get; init; } = string.Empty; - - /// Provider advanced-feature values. - [JsonPropertyName("enabled_advanced_features")] - public IReadOnlyList EnabledAdvancedFeatures { get; init; } = Array.Empty(); -} - -/// Advanced server features currently available to the account. -public sealed class AvailableAdvancedServerFeatures : BinaryLaneDto -{ - [JsonPropertyName("processor_models")] - public IReadOnlyList ProcessorModels { get; init; } = Array.Empty(); - - [JsonPropertyName("machine_types")] - public IReadOnlyList MachineTypes { get; init; } = Array.Empty(); - - [JsonPropertyName("advanced_features")] - public IReadOnlyList AdvancedFeatures { get; init; } = Array.Empty(); -} - -/// An available processor model. -public sealed class ProcessorModel : BinaryLaneDto -{ - [JsonPropertyName("id")] - public long Id { get; init; } - - [JsonPropertyName("name")] - public string Name { get; init; } = string.Empty; - - [JsonPropertyName("description")] - public string? Description { get; init; } -} - -/// An advanced firewall rule applied to a server. -public sealed class AdvancedFirewallRule : BinaryLaneDto -{ - [JsonPropertyName("source_addresses")] - public IReadOnlyList SourceAddresses { get; init; } = Array.Empty(); - - [JsonPropertyName("destination_addresses")] - public IReadOnlyList DestinationAddresses { get; init; } = Array.Empty(); - - [JsonPropertyName("destination_ports")] - public IReadOnlyList? DestinationPorts { get; init; } - - /// Provider protocol value, such as tcp. - [JsonPropertyName("protocol")] - public string Protocol { get; init; } = string.Empty; - - /// Provider action value, such as accept. - [JsonPropertyName("action")] - public string Action { get; init; } = string.Empty; - - [JsonPropertyName("description")] - public string? Description { get; init; } -} - -/// An available server kernel. -public sealed class Kernel : BinaryLaneDto -{ - [JsonPropertyName("id")] - public long Id { get; init; } - - [JsonPropertyName("name")] - public string? Name { get; init; } - - [JsonPropertyName("version")] - public string? Version { get; init; } -} - -/// A configured server threshold alert. -public sealed class ThresholdAlert : BinaryLaneDto -{ - /// Provider alert type. - [JsonPropertyName("alert_type")] - public string AlertType { get; init; } = string.Empty; - - [JsonPropertyName("name")] - public string Name { get; init; } = string.Empty; - - [JsonPropertyName("unit")] - public string Unit { get; init; } = string.Empty; - - [JsonPropertyName("description")] - public string Description { get; init; } = string.Empty; - - [JsonPropertyName("enabled")] - public bool Enabled { get; init; } - - [JsonPropertyName("value")] - public int Value { get; init; } - - [JsonPropertyName("current_value")] - public int? CurrentValue { get; init; } - - [JsonPropertyName("last_raised")] - public DateTimeOffset? LastRaised { get; init; } - - [JsonPropertyName("last_cleared")] - public DateTimeOffset? LastCleared { get; init; } -} - -/// Software licensed on a server. -public sealed class LicensedSoftware : BinaryLaneDto -{ - [JsonPropertyName("software")] - public Software Software { get; init; } = new(); - - [JsonPropertyName("licence_count")] - public int LicenceCount { get; init; } - - [JsonPropertyName("incompatible")] - public bool Incompatible { get; init; } -} - -/// A software product that can be licensed on BinaryLane servers. -public sealed class Software : BinaryLaneDto -{ - [JsonPropertyName("id")] - public long Id { get; init; } - - [JsonPropertyName("enabled")] - public bool Enabled { get; init; } - - [JsonPropertyName("name")] - public string Name { get; init; } = string.Empty; - - [JsonPropertyName("description")] - public string Description { get; init; } = string.Empty; - - [JsonPropertyName("cost_per_licence_per_month")] - public double CostPerLicencePerMonth { get; init; } - - [JsonPropertyName("minimum_licence_count")] - public int MinimumLicenceCount { get; init; } - - [JsonPropertyName("maximum_licence_count")] - public int MaximumLicenceCount { get; init; } - - [JsonPropertyName("licence_step_count")] - public int LicenceStepCount { get; init; } - - [JsonPropertyName("group")] - public string? Group { get; init; } - - [JsonPropertyName("supported_operating_systems")] - public IReadOnlyList SupportedOperatingSystems { get; init; } = Array.Empty(); -} - -/// A browser console session for a server. -public sealed class ServerConsole : BinaryLaneDto -{ - [JsonPropertyName("iframe")] - public string Iframe { get; init; } = string.Empty; - - [JsonPropertyName("browser")] - public string Browser { get; init; } = string.Empty; - - [JsonPropertyName("width")] - public int Width { get; init; } - - [JsonPropertyName("height")] - public int Height { get; init; } - - [JsonPropertyName("expiry")] - public DateTimeOffset Expiry { get; init; } -} - -/// Server user-data retained by BinaryLane. -public sealed class UserData : BinaryLaneDto -{ - [JsonPropertyName("user_data")] - public string? Value { get; init; } -} - -/// A sample interval for server monitoring data. -public sealed class Period : BinaryLaneDto -{ - [JsonPropertyName("start")] - public DateTimeOffset Start { get; init; } - - [JsonPropertyName("end")] - public DateTimeOffset End { get; init; } - - /// Provider interval, such as five-minute or day. - [JsonPropertyName("data_interval")] - public string DataInterval { get; init; } = string.Empty; -} - -/// One monitoring aggregate sample. -public sealed class Sample : BinaryLaneDto -{ - [JsonPropertyName("cpu_usage_percent")] - public double CpuUsagePercent { get; init; } - - [JsonPropertyName("cpu_usage_detailed")] - public IReadOnlyList CpuUsageDetailed { get; init; } = Array.Empty(); - - [JsonPropertyName("memory_usage_bytes")] - public double MemoryUsageBytes { get; init; } - - [JsonPropertyName("network_incoming_kbps")] - public double NetworkIncomingKbps { get; init; } - - [JsonPropertyName("network_outgoing_kbps")] - public double NetworkOutgoingKbps { get; init; } - - [JsonPropertyName("storage_usage_megabytes")] - public double StorageUsageMegabytes { get; init; } - - [JsonPropertyName("storage_read_kbps")] - public double StorageReadKbps { get; init; } - - [JsonPropertyName("storage_write_kbps")] - public double StorageWriteKbps { get; init; } - - [JsonPropertyName("storage_read_requests_per_second")] - public double StorageReadRequestsPerSecond { get; init; } - - [JsonPropertyName("storage_write_requests_per_second")] - public double StorageWriteRequestsPerSecond { get; init; } -} - -/// A set of monitoring samples for a server. -public sealed class SampleSet : BinaryLaneDto -{ - [JsonPropertyName("server_id")] - public long ServerId { get; init; } - - [JsonPropertyName("period")] - public Period Period { get; init; } = new(); - - [JsonPropertyName("average")] - public Sample Average { get; init; } = new(); - - [JsonPropertyName("maximum_memory_megabytes")] - public double MaximumMemoryMegabytes { get; init; } - - [JsonPropertyName("maximum_storage_gigabytes")] - public double MaximumStorageGigabytes { get; init; } -} diff --git a/src/BinaryLane.Api/Models/ResponseModels.cs b/src/BinaryLane.Api/Models/ResponseModels.cs deleted file mode 100644 index a24e4c8..0000000 --- a/src/BinaryLane.Api/Models/ResponseModels.cs +++ /dev/null @@ -1,472 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text.Json.Serialization; - -namespace BinaryLane.Api.V2.Models; - -/// Pagination metadata returned by BinaryLane list endpoints. -public sealed class PageMeta : BinaryLaneDto -{ - [JsonPropertyName("total")] - public int Total { get; init; } -} - -/// Pagination links returned by BinaryLane list endpoints. -public sealed class PageLinks : BinaryLaneDto -{ - [JsonPropertyName("pages")] - public PageNavigation Pages { get; init; } = new(); -} - -/// URLs for neighbouring pages in a BinaryLane list response. -public sealed class PageNavigation : BinaryLaneDto -{ - [JsonPropertyName("first")] - public string? First { get; init; } - - [JsonPropertyName("prev")] - public string? Previous { get; init; } - - [JsonPropertyName("next")] - public string? Next { get; init; } - - [JsonPropertyName("last")] - public string? Last { get; init; } -} - -/// An RFC 7807-style problem returned by BinaryLane. -public class ProblemDetails : BinaryLaneDto -{ - [JsonPropertyName("type")] - public string? Type { get; init; } - - [JsonPropertyName("title")] - public string? Title { get; init; } - - [JsonPropertyName("status")] - public int? Status { get; init; } - - [JsonPropertyName("detail")] - public string? Detail { get; init; } - - [JsonPropertyName("instance")] - public string? Instance { get; init; } -} - -/// A validation problem returned by BinaryLane. -public sealed class ValidationProblemDetails : ProblemDetails -{ - [JsonPropertyName("errors")] - public IReadOnlyDictionary>? Errors { get; init; } -} - -public sealed class AccountResponse : BinaryLaneDto -{ - [JsonPropertyName("account")] - public Account Account { get; init; } = new(); -} - -public sealed class ActionResponse : BinaryLaneDto -{ - [JsonPropertyName("action")] - public BinaryLaneAction Action { get; init; } = new(); -} - -public sealed class ActionsLinks : BinaryLaneDto -{ - [JsonPropertyName("actions")] - public IReadOnlyList Actions { get; init; } = Array.Empty(); -} - -public sealed class ActionsResponse : BinaryLaneDto -{ - [JsonPropertyName("meta")] - public PageMeta Meta { get; init; } = new(); - - [JsonPropertyName("links")] - public PageLinks? Links { get; init; } - - [JsonPropertyName("actions")] - public IReadOnlyList Actions { get; init; } = Array.Empty(); -} - -public sealed class BalanceResponse : BinaryLaneDto -{ - [JsonPropertyName("balance")] - public Balance Balance { get; init; } = new(); -} - -public sealed class InvoiceResponse : BinaryLaneDto -{ - [JsonPropertyName("invoice")] - public Invoice Invoice { get; init; } = new(); -} - -public sealed class InvoicesResponse : BinaryLaneDto -{ - [JsonPropertyName("meta")] - public PageMeta Meta { get; init; } = new(); - - [JsonPropertyName("links")] - public PageLinks? Links { get; init; } - - [JsonPropertyName("invoices")] - public IReadOnlyList Invoices { get; init; } = Array.Empty(); -} - -public sealed class UnpaidFailedInvoicesResponse : BinaryLaneDto -{ - [JsonPropertyName("invoices")] - public IReadOnlyList Invoices { get; init; } = Array.Empty(); -} - -public sealed class DataUsageResponse : BinaryLaneDto -{ - [JsonPropertyName("data_usage")] - public DataUsage DataUsage { get; init; } = new(); -} - -public sealed class DataUsagesResponse : BinaryLaneDto -{ - [JsonPropertyName("meta")] - public PageMeta Meta { get; init; } = new(); - - [JsonPropertyName("links")] - public PageLinks? Links { get; init; } - - [JsonPropertyName("data_usages")] - public IReadOnlyList DataUsages { get; init; } = Array.Empty(); -} - -public sealed class LocalNameserversResponse : BinaryLaneDto -{ - [JsonPropertyName("local_nameservers")] - public IReadOnlyList LocalNameservers { get; init; } = Array.Empty(); -} - -public sealed class DomainResponse : BinaryLaneDto -{ - [JsonPropertyName("domain")] - public Domain Domain { get; init; } = new(); -} - -public sealed class DomainsResponse : BinaryLaneDto -{ - [JsonPropertyName("meta")] - public PageMeta Meta { get; init; } = new(); - - [JsonPropertyName("links")] - public PageLinks? Links { get; init; } - - [JsonPropertyName("domains")] - public IReadOnlyList Domains { get; init; } = Array.Empty(); -} - -public sealed class DomainRecordResponse : BinaryLaneDto -{ - [JsonPropertyName("domain_record")] - public DomainRecord DomainRecord { get; init; } = new(); -} - -public sealed class DomainRecordsResponse : BinaryLaneDto -{ - [JsonPropertyName("meta")] - public PageMeta Meta { get; init; } = new(); - - [JsonPropertyName("links")] - public PageLinks? Links { get; init; } - - [JsonPropertyName("domain_records")] - public IReadOnlyList DomainRecords { get; init; } = Array.Empty(); -} - -public sealed class ImageResponse : BinaryLaneDto -{ - [JsonPropertyName("image")] - public Image Image { get; init; } = new(); -} - -public sealed class ImagesResponse : BinaryLaneDto -{ - [JsonPropertyName("meta")] - public PageMeta Meta { get; init; } = new(); - - [JsonPropertyName("links")] - public PageLinks? Links { get; init; } - - [JsonPropertyName("images")] - public IReadOnlyList Images { get; init; } = Array.Empty(); -} - -public sealed class ImageDownloadResponse : BinaryLaneDto -{ - [JsonPropertyName("link")] - public ImageDownload Link { get; init; } = new(); -} - -public sealed class SshKeyResponse : BinaryLaneDto -{ - [JsonPropertyName("ssh_key")] - public SshKey SshKey { get; init; } = new(); -} - -public sealed class SshKeysResponse : BinaryLaneDto -{ - [JsonPropertyName("meta")] - public PageMeta Meta { get; init; } = new(); - - [JsonPropertyName("links")] - public PageLinks? Links { get; init; } - - [JsonPropertyName("ssh_keys")] - public IReadOnlyList SshKeys { get; init; } = Array.Empty(); -} - -public sealed class LoadBalancerResponse : BinaryLaneDto -{ - [JsonPropertyName("load_balancer")] - public LoadBalancer LoadBalancer { get; init; } = new(); -} - -public sealed class LoadBalancersResponse : BinaryLaneDto -{ - [JsonPropertyName("meta")] - public PageMeta Meta { get; init; } = new(); - - [JsonPropertyName("links")] - public PageLinks? Links { get; init; } - - [JsonPropertyName("load_balancers")] - public IReadOnlyList LoadBalancers { get; init; } = Array.Empty(); -} - -public sealed class CreateLoadBalancerResponse : BinaryLaneDto -{ - [JsonPropertyName("load_balancer")] - public LoadBalancer LoadBalancer { get; init; } = new(); - - [JsonPropertyName("links")] - public ActionsLinks Links { get; init; } = new(); -} - -public sealed class UpdateLoadBalancerResponse : BinaryLaneDto -{ - [JsonPropertyName("load_balancer")] - public LoadBalancer LoadBalancer { get; init; } = new(); - - [JsonPropertyName("links")] - public ActionsLinks? Links { get; init; } -} - -public sealed class LoadBalancerAvailabilityResponse : BinaryLaneDto -{ - [JsonPropertyName("load_balancer_availability_options")] - public IReadOnlyList LoadBalancerAvailabilityOptions { get; init; } = Array.Empty(); -} - -public sealed class RegionsResponse : BinaryLaneDto -{ - [JsonPropertyName("meta")] - public PageMeta Meta { get; init; } = new(); - - [JsonPropertyName("links")] - public PageLinks? Links { get; init; } - - [JsonPropertyName("regions")] - public IReadOnlyList Regions { get; init; } = Array.Empty(); -} - -public sealed class ReverseNameServersResponse : BinaryLaneDto -{ - [JsonPropertyName("meta")] - public PageMeta Meta { get; init; } = new(); - - [JsonPropertyName("links")] - public PageLinks? Links { get; init; } - - [JsonPropertyName("reverse_nameservers")] - public IReadOnlyList ReverseNameservers { get; init; } = Array.Empty(); -} - -public sealed class SampleSetResponse : BinaryLaneDto -{ - [JsonPropertyName("sample_set")] - public SampleSet? SampleSet { get; init; } -} - -public sealed class SampleSetsResponse : BinaryLaneDto -{ - [JsonPropertyName("meta")] - public PageMeta Meta { get; init; } = new(); - - [JsonPropertyName("links")] - public PageLinks? Links { get; init; } - - [JsonPropertyName("sample_sets")] - public IReadOnlyList SampleSets { get; init; } = Array.Empty(); -} - -public sealed class ServerResponse : BinaryLaneDto -{ - [JsonPropertyName("server")] - public Server Server { get; init; } = new(); -} - -public sealed class ServersResponse : BinaryLaneDto -{ - [JsonPropertyName("meta")] - public PageMeta Meta { get; init; } = new(); - - [JsonPropertyName("links")] - public PageLinks? Links { get; init; } - - [JsonPropertyName("servers")] - public IReadOnlyList Servers { get; init; } = Array.Empty(); -} - -public sealed class CreateServerResponse : BinaryLaneDto -{ - [JsonPropertyName("server")] - public Server Server { get; init; } = new(); - - [JsonPropertyName("links")] - public ActionsLinks Links { get; init; } = new(); -} - -public sealed class AdvancedFirewallRulesResponse : BinaryLaneDto -{ - [JsonPropertyName("firewall_rules")] - public IReadOnlyList FirewallRules { get; init; } = Array.Empty(); -} - -public sealed class AvailableAdvancedServerFeaturesResponse : BinaryLaneDto -{ - [JsonPropertyName("available_advanced_server_features")] - public AvailableAdvancedServerFeatures AvailableAdvancedServerFeatures { get; init; } = new(); -} - -public sealed class BackupsResponse : BinaryLaneDto -{ - [JsonPropertyName("meta")] - public PageMeta Meta { get; init; } = new(); - - [JsonPropertyName("links")] - public PageLinks? Links { get; init; } - - [JsonPropertyName("backups")] - public IReadOnlyList Backups { get; init; } = Array.Empty(); -} - -public sealed class KernelsResponse : BinaryLaneDto -{ - [JsonPropertyName("meta")] - public PageMeta Meta { get; init; } = new(); - - [JsonPropertyName("links")] - public PageLinks? Links { get; init; } - - [JsonPropertyName("kernels")] - public IReadOnlyList Kernels { get; init; } = Array.Empty(); -} - -public sealed class SnapshotsResponse : BinaryLaneDto -{ - [JsonPropertyName("meta")] - public PageMeta Meta { get; init; } = new(); - - [JsonPropertyName("links")] - public PageLinks? Links { get; init; } - - [JsonPropertyName("snapshots")] - public IReadOnlyList Snapshots { get; init; } = Array.Empty(); -} - -public sealed class ThresholdAlertsResponse : BinaryLaneDto -{ - [JsonPropertyName("threshold_alerts")] - public IReadOnlyList ThresholdAlerts { get; init; } = Array.Empty(); -} - -public sealed class CurrentServerAlertsResponse : BinaryLaneDto -{ - [JsonPropertyName("server_ids")] - public IReadOnlyList ServerIds { get; init; } = Array.Empty(); -} - -public sealed class LicensedSoftwaresResponse : BinaryLaneDto -{ - [JsonPropertyName("meta")] - public PageMeta Meta { get; init; } = new(); - - [JsonPropertyName("links")] - public PageLinks? Links { get; init; } - - [JsonPropertyName("licensed_software")] - public IReadOnlyList LicensedSoftware { get; init; } = Array.Empty(); -} - -public sealed class ServerConsoleResponse : BinaryLaneDto -{ - [JsonPropertyName("console")] - public ServerConsole Console { get; init; } = new(); -} - -public sealed class SizesResponse : BinaryLaneDto -{ - [JsonPropertyName("meta")] - public PageMeta Meta { get; init; } = new(); - - [JsonPropertyName("links")] - public PageLinks? Links { get; init; } - - [JsonPropertyName("sizes")] - public IReadOnlyList Sizes { get; init; } = Array.Empty(); -} - -public sealed class SoftwareResponse : BinaryLaneDto -{ - [JsonPropertyName("software")] - public Software Software { get; init; } = new(); -} - -public sealed class SoftwaresResponse : BinaryLaneDto -{ - [JsonPropertyName("meta")] - public PageMeta Meta { get; init; } = new(); - - [JsonPropertyName("links")] - public PageLinks? Links { get; init; } - - [JsonPropertyName("software")] - public IReadOnlyList Software { get; init; } = Array.Empty(); -} - -public sealed class VpcResponse : BinaryLaneDto -{ - [JsonPropertyName("vpc")] - public Vpc Vpc { get; init; } = new(); -} - -public sealed class VpcsResponse : BinaryLaneDto -{ - [JsonPropertyName("meta")] - public PageMeta Meta { get; init; } = new(); - - [JsonPropertyName("links")] - public PageLinks? Links { get; init; } - - [JsonPropertyName("vpcs")] - public IReadOnlyList Vpcs { get; init; } = Array.Empty(); -} - -public sealed class VpcMembersResponse : BinaryLaneDto -{ - [JsonPropertyName("meta")] - public PageMeta Meta { get; init; } = new(); - - [JsonPropertyName("links")] - public PageLinks? Links { get; init; } - - [JsonPropertyName("members")] - public IReadOnlyList Members { get; init; } = Array.Empty(); -} diff --git a/src/BinaryLane.Api/Models/ReverseNames/ReverseNamesModels.cs b/src/BinaryLane.Api/Models/ReverseNames/ReverseNamesModels.cs new file mode 100644 index 0000000..7d6e59b --- /dev/null +++ b/src/BinaryLane.Api/Models/ReverseNames/ReverseNamesModels.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace BinaryLane.Api.V2.Models; + +/// Updates the IPv6 reverse nameservers configured for the account. +public sealed class ReverseNameserversRequest : BinaryLaneRequestModel +{ + [JsonPropertyName("reverse_nameservers")] + public IReadOnlyList ReverseNameservers { get; init; } = Array.Empty(); +} + +public sealed class ReverseNameServersResponse : BinaryLaneDto +{ + [JsonPropertyName("meta")] + public PageMeta Meta { get; init; } = new(); + + [JsonPropertyName("links")] + public PageLinks? Links { get; init; } + + [JsonPropertyName("reverse_nameservers")] + public IReadOnlyList ReverseNameservers { get; init; } = Array.Empty(); +} diff --git a/src/BinaryLane.Api/Models/ServerActionModels.cs b/src/BinaryLane.Api/Models/ServerActionModels.cs deleted file mode 100644 index e9066b6..0000000 --- a/src/BinaryLane.Api/Models/ServerActionModels.cs +++ /dev/null @@ -1,521 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text.Json.Serialization; - -namespace BinaryLane.Api.V2.Models; - -/// -/// Base payload for POST /v2/servers/{server_id}/actions. -/// -/// -/// The upstream contract is a discriminated union on type. Its public -/// documentation also creates fragment-bearing pseudo-paths for each variant; -/// those are not separate HTTP routes. Prefer a concrete derived type for a -/// documented action. permits new provider -/// action types without waiting for an SDK release. -/// -public class ServerAction : BinaryLaneRequestModel -{ - /// Creates an empty action for serializers and advanced callers. - public ServerAction() - { - } - - /// Creates a typed action with the provider discriminator value. - protected ServerAction(string type) - { - Type = type; - } - - [JsonPropertyName("type")] - public string Type { get; init; } = string.Empty; -} - -/// An action type not yet represented by a concrete SDK class. -public sealed class UnknownServerAction : ServerAction -{ - public UnknownServerAction(string type) - : base(type) - { - } -} - -/// Adds an additional disk to a server. -public sealed class AddDiskServerAction : ServerAction -{ - public AddDiskServerAction() : base("add_disk") { } - - [JsonPropertyName("size_gigabytes")] - public int SizeGigabytes { get; init; } - - [JsonPropertyName("description")] - public string? Description { get; init; } -} - -/// Attaches a backup image to a server. -public sealed class AttachBackupServerAction : ServerAction -{ - public AttachBackupServerAction() : base("attach_backup") { } - - [JsonPropertyName("image")] - public long ImageId { get; init; } -} - -/// Changes advanced virtual-machine features. -public sealed class ChangeAdvancedFeaturesServerAction : ServerAction -{ - public ChangeAdvancedFeaturesServerAction() : base("change_advanced_features") { } - - [JsonPropertyName("enabled_advanced_features")] - public IReadOnlyList? EnabledAdvancedFeatures { get; init; } - - [JsonPropertyName("processor_model")] - public long? ProcessorModel { get; init; } - - [JsonPropertyName("automatic_processor_model")] - public bool? AutomaticProcessorModel { get; init; } - - [JsonPropertyName("machine_type")] - public string? MachineType { get; init; } - - [JsonPropertyName("automatic_machine_type")] - public bool? AutomaticMachineType { get; init; } - - [JsonPropertyName("video_device")] - public string? VideoDevice { get; init; } -} - -/// Replaces the advanced firewall rules on a server. -public sealed class ChangeAdvancedFirewallRulesServerAction : ServerAction -{ - public ChangeAdvancedFirewallRulesServerAction() : base("change_advanced_firewall_rules") { } - - [JsonPropertyName("firewall_rules")] - public IReadOnlyList FirewallRules { get; init; } = Array.Empty(); -} - -/// Changes a server backup schedule. -public sealed class ChangeBackupScheduleServerAction : ServerAction -{ - public ChangeBackupScheduleServerAction() : base("change_backup_schedule") { } - - [JsonPropertyName("backup_hour_of_day")] - public int? BackupHourOfDay { get; init; } - - [JsonPropertyName("backup_day_of_week")] - public int? BackupDayOfWeek { get; init; } - - [JsonPropertyName("backup_day_of_month")] - public int? BackupDayOfMonth { get; init; } -} - -/// Enables or disables IPv6 for a server. -public sealed class ChangeIpv6ServerAction : ServerAction -{ - public ChangeIpv6ServerAction() : base("change_ipv6") { } - - [JsonPropertyName("enabled")] - public bool Enabled { get; init; } -} - -/// Changes a server's IPv6 reverse nameservers. -public sealed class ChangeIpv6ReverseNameserversServerAction : ServerAction -{ - public ChangeIpv6ReverseNameserversServerAction() : base("change_ipv6_reverse_nameservers") { } - - [JsonPropertyName("ipv6_reverse_nameservers")] - public IReadOnlyList Ipv6ReverseNameservers { get; init; } = Array.Empty(); -} - -/// Changes a server kernel. -public sealed class ChangeKernelServerAction : ServerAction -{ - public ChangeKernelServerAction() : base("change_kernel") { } - - [JsonPropertyName("kernel")] - public long KernelId { get; init; } -} - -/// Changes whether offsite backup copies are managed automatically. -public sealed class ChangeManageOffsiteBackupCopiesServerAction : ServerAction -{ - public ChangeManageOffsiteBackupCopiesServerAction() : base("change_manage_offsite_backup_copies") { } - - [JsonPropertyName("manage_offsite_backup_copies")] - public bool ManageOffsiteBackupCopies { get; init; } -} - -/// Moves a server onto or off a VPC network. -public sealed class ChangeNetworkServerAction : ServerAction -{ - public ChangeNetworkServerAction() : base("change_network") { } - - [JsonPropertyName("vpc_id")] - public long? VpcId { get; init; } -} - -/// Changes the server's offsite backup location. -public sealed class ChangeOffsiteBackupLocationServerAction : ServerAction -{ - public ChangeOffsiteBackupLocationServerAction() : base("change_offsite_backup_location") { } - - [JsonPropertyName("offsite_backup_location")] - public string? OffsiteBackupLocation { get; init; } -} - -/// Changes the server's partner server relationship. -public sealed class ChangePartnerServerAction : ServerAction -{ - public ChangePartnerServerAction() : base("change_partner") { } - - [JsonPropertyName("partner_server_id")] - public long? PartnerServerId { get; init; } -} - -/// Enables or disables port blocking. -public sealed class ChangePortBlockingServerAction : ServerAction -{ - public ChangePortBlockingServerAction() : base("change_port_blocking") { } - - [JsonPropertyName("enabled")] - public bool Enabled { get; init; } -} - -/// Moves a server to a new region. -public sealed class ChangeRegionServerAction : ServerAction -{ - public ChangeRegionServerAction() : base("change_region") { } - - [JsonPropertyName("region")] - public string Region { get; init; } = string.Empty; -} - -/// Changes an IPv4 reverse name. -public sealed class ChangeReverseNameServerAction : ServerAction -{ - public ChangeReverseNameServerAction() : base("change_reverse_name") { } - - [JsonPropertyName("ipv4_address")] - public string Ipv4Address { get; init; } = string.Empty; - - [JsonPropertyName("reverse_name")] - public string? ReverseName { get; init; } -} - -/// Enables or disables a separate private network interface. -public sealed class ChangeSeparatePrivateNetworkInterfaceServerAction : ServerAction -{ - public ChangeSeparatePrivateNetworkInterfaceServerAction() : base("change_separate_private_network_interface") { } - - [JsonPropertyName("enabled")] - public bool Enabled { get; init; } -} - -/// Enables or disables source-and-destination checking. -public sealed class ChangeSourceAndDestinationCheckServerAction : ServerAction -{ - public ChangeSourceAndDestinationCheckServerAction() : base("change_source_and_destination_check") { } - - [JsonPropertyName("enabled")] - public bool Enabled { get; init; } -} - -/// Replaces a server's threshold-alert configuration. -public sealed class ChangeThresholdAlertsServerAction : ServerAction -{ - public ChangeThresholdAlertsServerAction() : base("change_threshold_alerts") { } - - [JsonPropertyName("threshold_alerts")] - public IReadOnlyList ThresholdAlerts { get; init; } = Array.Empty(); -} - -/// Changes a VPC IPv4 address on a server. -public sealed class ChangeVpcIpv4ServerAction : ServerAction -{ - public ChangeVpcIpv4ServerAction() : base("change_vpc_ipv4") { } - - [JsonPropertyName("current_ipv4_address")] - public string CurrentIpv4Address { get; init; } = string.Empty; - - [JsonPropertyName("new_ipv4_address")] - public string NewIpv4Address { get; init; } = string.Empty; -} - -/// Clones a backup image onto another server. -public sealed class CloneUsingBackupServerAction : ServerAction -{ - public CloneUsingBackupServerAction() : base("clone_using_backup") { } - - [JsonPropertyName("image_id")] - public long ImageId { get; init; } - - [JsonPropertyName("target_server_id")] - public long TargetServerId { get; init; } - - [JsonPropertyName("name")] - public string? Name { get; init; } -} - -/// Deletes a non-primary disk. -public sealed class DeleteDiskServerAction : ServerAction -{ - public DeleteDiskServerAction() : base("delete_disk") { } - - [JsonPropertyName("disk_id")] - public long DiskId { get; init; } -} - -/// Detaches an attached backup from a server. -public sealed class DetachBackupServerAction : ServerAction -{ - public DetachBackupServerAction() : base("detach_backup") { } -} - -/// Disables automatic backups. -public sealed class DisableBackupsServerAction : ServerAction -{ - public DisableBackupsServerAction() : base("disable_backups") { } -} - -/// Disables SELinux in a compatible installed distribution. -public sealed class DisableSelinuxServerAction : ServerAction -{ - public DisableSelinuxServerAction() : base("disable_selinux") { } -} - -/// Enables automatic backups. -public sealed class EnableBackupsServerAction : ServerAction -{ - public EnableBackupsServerAction() : base("enable_backups") { } -} - -/// Enables IPv6 on a server. -public sealed class EnableIpv6ServerAction : ServerAction -{ - public EnableIpv6ServerAction() : base("enable_ipv6") { } -} - -/// Checks whether a server is running. -public sealed class IsRunningServerAction : ServerAction -{ - public IsRunningServerAction() : base("is_running") { } -} - -/// Resets a server password. -public sealed class PasswordResetServerAction : ServerAction -{ - public PasswordResetServerAction() : base("password_reset") { } - - [JsonPropertyName("username")] - public string? Username { get; init; } - - /// Do not log this value. - [JsonPropertyName("password")] - public string? Password { get; init; } -} - -/// Pings a server. -public sealed class PingServerAction : ServerAction -{ - public PingServerAction() : base("ping") { } -} - -/// Power cycles a server. -public sealed class PowerCycleServerAction : ServerAction -{ - public PowerCycleServerAction() : base("power_cycle") { } -} - -/// Powers a server off. -public sealed class PowerOffServerAction : ServerAction -{ - public PowerOffServerAction() : base("power_off") { } -} - -/// Powers a server on. -public sealed class PowerOnServerAction : ServerAction -{ - public PowerOnServerAction() : base("power_on") { } -} - -/// Reboots a server. -public sealed class RebootServerAction : ServerAction -{ - public RebootServerAction() : base("reboot") { } -} - -/// Rebuilds a server from an image. -public sealed class RebuildServerAction : ServerAction -{ - public RebuildServerAction() : base("rebuild") { } - - /// An image ID or image slug. Omit to reuse the existing image. - [JsonPropertyName("image")] - public object? Image { get; init; } - - [JsonPropertyName("options")] - public ImageOptions? Options { get; init; } -} - -/// Renames a server. -public sealed class RenameServerAction : ServerAction -{ - public RenameServerAction() : base("rename") { } - - [JsonPropertyName("name")] - public string Name { get; init; } = string.Empty; -} - -/// Changes selected size options during a resize action. -public sealed class ChangeSizeOptionsRequest : BinaryLaneRequestModel -{ - [JsonPropertyName("daily_backups")] - public int? DailyBackups { get; init; } - - [JsonPropertyName("weekly_backups")] - public int? WeeklyBackups { get; init; } - - [JsonPropertyName("monthly_backups")] - public int? MonthlyBackups { get; init; } - - [JsonPropertyName("offsite_backups")] - public bool? OffsiteBackups { get; init; } - - [JsonPropertyName("ipv4_addresses")] - public int? Ipv4Addresses { get; init; } - - [JsonPropertyName("memory")] - public int? MemoryMegabytes { get; init; } - - [JsonPropertyName("disk")] - public int? DiskGigabytes { get; init; } - - [JsonPropertyName("transfer")] - public double? TransferGigabytes { get; init; } - - [JsonPropertyName("ipv4_addresses_to_remove")] - public IReadOnlyList? Ipv4AddressesToRemove { get; init; } -} - -/// Changes the source image selected by a resize operation. -public sealed class ChangeImage : BinaryLaneRequestModel -{ - /// An image ID or image slug. - [JsonPropertyName("image")] - public object? Image { get; init; } - - [JsonPropertyName("options")] - public ImageOptions? Options { get; init; } -} - -/// Changes licences selected by a resize operation. -public sealed class ChangeLicenses : BinaryLaneRequestModel -{ - [JsonPropertyName("licenses")] - public IReadOnlyList Licenses { get; init; } = Array.Empty(); -} - -/// Resizes a server. -public sealed class ResizeServerAction : ServerAction -{ - public ResizeServerAction() : base("resize") { } - - [JsonPropertyName("size")] - public string? Size { get; init; } - - [JsonPropertyName("options")] - public ChangeSizeOptionsRequest? Options { get; init; } - - [JsonPropertyName("change_image")] - public ChangeImage? ChangeImage { get; init; } - - [JsonPropertyName("change_licenses")] - public ChangeLicenses? ChangeLicenses { get; init; } - - [JsonPropertyName("pre_action_backup")] - public TakeBackupServerAction? PreActionBackup { get; init; } -} - -/// Resizes an individual server disk. -public sealed class ResizeDiskServerAction : ServerAction -{ - public ResizeDiskServerAction() : base("resize_disk") { } - - [JsonPropertyName("disk_id")] - public long DiskId { get; init; } - - [JsonPropertyName("size_gigabytes")] - public int SizeGigabytes { get; init; } -} - -/// Restores a server from an image. -public sealed class RestoreServerAction : ServerAction -{ - public RestoreServerAction() : base("restore") { } - - /// An image ID or image slug. - [JsonPropertyName("image")] - public object Image { get; init; } = string.Empty; -} - -/// Requests a graceful shutdown. -public sealed class ShutdownServerAction : ServerAction -{ - public ShutdownServerAction() : base("shutdown") { } -} - -/// Creates a backup of a server. -public sealed class TakeBackupServerAction : ServerAction -{ - public TakeBackupServerAction() : base("take_backup") { } - - /// Provider backup slot, such as daily or temporary. - [JsonPropertyName("backup_type")] - public string? BackupType { get; init; } - - /// Provider replacement strategy. - [JsonPropertyName("replacement_strategy")] - public string ReplacementStrategy { get; init; } = string.Empty; - - [JsonPropertyName("backup_id_to_replace")] - public long? BackupIdToReplace { get; init; } - - [JsonPropertyName("label")] - public string? Label { get; init; } -} - -/// Reverses a scheduled server cancellation. -public sealed class UncancelServerAction : ServerAction -{ - public UncancelServerAction() : base("uncancel") { } -} - -/// Checks server uptime. -public sealed class UptimeServerAction : ServerAction -{ - public UptimeServerAction() : base("uptime") { } -} - -/// An advanced firewall rule supplied in a server-action request. -public sealed class AdvancedFirewallRuleRequest : BinaryLaneRequestModel -{ - [JsonPropertyName("source_addresses")] - public IReadOnlyList SourceAddresses { get; init; } = Array.Empty(); - - [JsonPropertyName("destination_addresses")] - public IReadOnlyList DestinationAddresses { get; init; } = Array.Empty(); - - [JsonPropertyName("destination_ports")] - public IReadOnlyList? DestinationPorts { get; init; } - - /// Provider protocol value, such as tcp. - [JsonPropertyName("protocol")] - public string Protocol { get; init; } = string.Empty; - - /// Provider action value, such as accept. - [JsonPropertyName("action")] - public string Action { get; init; } = string.Empty; - - [JsonPropertyName("description")] - public string? Description { get; init; } -} diff --git a/src/BinaryLane.Api/Models/ServerActions/ServerAction.cs b/src/BinaryLane.Api/Models/ServerActions/ServerAction.cs new file mode 100644 index 0000000..3611bcb --- /dev/null +++ b/src/BinaryLane.Api/Models/ServerActions/ServerAction.cs @@ -0,0 +1,44 @@ +using System.Text.Json.Serialization; + +namespace BinaryLane.Api.V2.Models; + +/// +/// Base payload for POST /v2/servers/{server_id}/actions. +/// +/// +/// The upstream contract is a discriminated union on type. Its public +/// documentation also creates fragment-bearing pseudo-paths for each variant; +/// those are not separate HTTP routes. Prefer a concrete derived type for a +/// documented action. permits new provider +/// action types without waiting for an SDK release. +/// +public class ServerAction : BinaryLaneRequestModel +{ + /// Creates an empty action for serializers and advanced callers. + public ServerAction() + { + } + + /// Creates a typed action with the provider discriminator value. + protected ServerAction(string type) + { + Type = type; + } + + [JsonPropertyName(ServerActionJsonNames.Type)] + public string Type { get; init; } = string.Empty; +} + +internal static class ServerActionJsonNames +{ + internal const string Type = "type"; +} + +/// An action type not yet represented by a concrete SDK class. +public sealed class UnknownServerAction : ServerAction +{ + public UnknownServerAction(string type) + : base(type) + { + } +} diff --git a/src/BinaryLane.Api/Models/ServerActions/ServerActionBackupAndStorageModels.cs b/src/BinaryLane.Api/Models/ServerActions/ServerActionBackupAndStorageModels.cs new file mode 100644 index 0000000..20713a8 --- /dev/null +++ b/src/BinaryLane.Api/Models/ServerActions/ServerActionBackupAndStorageModels.cs @@ -0,0 +1,150 @@ +using System.Text.Json.Serialization; + +namespace BinaryLane.Api.V2.Models; + +/// Adds an additional disk to a server. +public sealed class AddDiskServerAction : ServerAction +{ + public AddDiskServerAction() : base(BinaryLaneValues.ServerActionType.AddDisk) { } + + [JsonPropertyName("size_gigabytes")] + public int SizeGigabytes { get; init; } + + [JsonPropertyName("description")] + public string? Description { get; init; } +} + +/// Attaches a backup image to a server. +public sealed class AttachBackupServerAction : ServerAction +{ + public AttachBackupServerAction() : base(BinaryLaneValues.ServerActionType.AttachBackup) { } + + [JsonPropertyName("image")] + public long ImageId { get; init; } +} + +/// Changes a server backup schedule. +public sealed class ChangeBackupScheduleServerAction : ServerAction +{ + public ChangeBackupScheduleServerAction() : base(BinaryLaneValues.ServerActionType.ChangeBackupSchedule) { } + + [JsonPropertyName("backup_hour_of_day")] + public int? BackupHourOfDay { get; init; } + + [JsonPropertyName("backup_day_of_week")] + public int? BackupDayOfWeek { get; init; } + + [JsonPropertyName("backup_day_of_month")] + public int? BackupDayOfMonth { get; init; } +} + +/// Changes a server kernel. +public sealed class ChangeKernelServerAction : ServerAction +{ + public ChangeKernelServerAction() : base(BinaryLaneValues.ServerActionType.ChangeKernel) { } + + [JsonPropertyName("kernel")] + public long KernelId { get; init; } +} + +/// Changes whether offsite backup copies are managed automatically. +public sealed class ChangeManageOffsiteBackupCopiesServerAction : ServerAction +{ + public ChangeManageOffsiteBackupCopiesServerAction() : base(BinaryLaneValues.ServerActionType.ChangeManageOffsiteBackupCopies) { } + + [JsonPropertyName("manage_offsite_backup_copies")] + public bool ManageOffsiteBackupCopies { get; init; } +} + +/// Changes the server's offsite backup location. +public sealed class ChangeOffsiteBackupLocationServerAction : ServerAction +{ + public ChangeOffsiteBackupLocationServerAction() : base(BinaryLaneValues.ServerActionType.ChangeOffsiteBackupLocation) { } + + [JsonPropertyName("offsite_backup_location")] + public string? OffsiteBackupLocation { get; init; } +} + +/// Clones a backup image onto another server. +public sealed class CloneUsingBackupServerAction : ServerAction +{ + public CloneUsingBackupServerAction() : base(BinaryLaneValues.ServerActionType.CloneUsingBackup) { } + + [JsonPropertyName("image_id")] + public long ImageId { get; init; } + + [JsonPropertyName("target_server_id")] + public long TargetServerId { get; init; } + + [JsonPropertyName("name")] + public string? Name { get; init; } +} + +/// Deletes a non-primary disk. +public sealed class DeleteDiskServerAction : ServerAction +{ + public DeleteDiskServerAction() : base(BinaryLaneValues.ServerActionType.DeleteDisk) { } + + [JsonPropertyName("disk_id")] + public long DiskId { get; init; } +} + +/// Detaches an attached backup from a server. +public sealed class DetachBackupServerAction : ServerAction +{ + public DetachBackupServerAction() : base(BinaryLaneValues.ServerActionType.DetachBackup) { } +} + +/// Disables automatic backups. +public sealed class DisableBackupsServerAction : ServerAction +{ + public DisableBackupsServerAction() : base(BinaryLaneValues.ServerActionType.DisableBackups) { } +} + +/// Enables automatic backups. +public sealed class EnableBackupsServerAction : ServerAction +{ + public EnableBackupsServerAction() : base(BinaryLaneValues.ServerActionType.EnableBackups) { } +} + +/// Resizes an individual server disk. +public sealed class ResizeDiskServerAction : ServerAction +{ + public ResizeDiskServerAction() : base(BinaryLaneValues.ServerActionType.ResizeDisk) { } + + [JsonPropertyName("disk_id")] + public long DiskId { get; init; } + + [JsonPropertyName("size_gigabytes")] + public int SizeGigabytes { get; init; } +} + +/// Restores a server from an image. +public sealed class RestoreServerAction : ServerAction +{ + public RestoreServerAction() : base(BinaryLaneValues.ServerActionType.Restore) { } + + /// An image ID or image slug. + [JsonPropertyName("image")] + public object Image { get; init; } = string.Empty; +} + +/// Creates a backup of a server. +public sealed class TakeBackupServerAction : ServerAction +{ + public TakeBackupServerAction() : base(BinaryLaneValues.ServerActionType.TakeBackup) { } + + /// Provider backup slot, such as daily or temporary. + [JsonPropertyName("backup_type")] + public string? BackupType { get; init; } + + /// Provider replacement strategy. + [JsonPropertyName("replacement_strategy")] + public string ReplacementStrategy { get; init; } = string.Empty; + + [JsonPropertyName("backup_id_to_replace")] + public long? BackupIdToReplace { get; init; } + + [JsonPropertyName("label")] + public string? Label { get; init; } +} diff --git a/src/BinaryLane.Api/Models/ServerActions/ServerActionConfigurationModels.cs b/src/BinaryLane.Api/Models/ServerActions/ServerActionConfigurationModels.cs new file mode 100644 index 0000000..7187174 --- /dev/null +++ b/src/BinaryLane.Api/Models/ServerActions/ServerActionConfigurationModels.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace BinaryLane.Api.V2.Models; + +/// Changes advanced virtual-machine features. +public sealed class ChangeAdvancedFeaturesServerAction : ServerAction +{ + public ChangeAdvancedFeaturesServerAction() : base(BinaryLaneValues.ServerActionType.ChangeAdvancedFeatures) { } + + [JsonPropertyName("enabled_advanced_features")] + public IReadOnlyList? EnabledAdvancedFeatures { get; init; } + + [JsonPropertyName("processor_model")] + public long? ProcessorModel { get; init; } + + [JsonPropertyName("automatic_processor_model")] + public bool? AutomaticProcessorModel { get; init; } + + [JsonPropertyName("machine_type")] + public string? MachineType { get; init; } + + [JsonPropertyName("automatic_machine_type")] + public bool? AutomaticMachineType { get; init; } + + [JsonPropertyName("video_device")] + public string? VideoDevice { get; init; } +} + +/// Replaces the advanced firewall rules on a server. +public sealed class ChangeAdvancedFirewallRulesServerAction : ServerAction +{ + public ChangeAdvancedFirewallRulesServerAction() : base(BinaryLaneValues.ServerActionType.ChangeAdvancedFirewallRules) { } + + [JsonPropertyName("firewall_rules")] + public IReadOnlyList FirewallRules { get; init; } = Array.Empty(); +} + +/// Enables or disables port blocking. +public sealed class ChangePortBlockingServerAction : ServerAction +{ + public ChangePortBlockingServerAction() : base(BinaryLaneValues.ServerActionType.ChangePortBlocking) { } + + [JsonPropertyName("enabled")] + public bool Enabled { get; init; } +} + +/// Moves a server to a new region. +public sealed class ChangeRegionServerAction : ServerAction +{ + public ChangeRegionServerAction() : base(BinaryLaneValues.ServerActionType.ChangeRegion) { } + + [JsonPropertyName("region")] + public string Region { get; init; } = string.Empty; +} + +/// Changes a server's partner server relationship. +public sealed class ChangePartnerServerAction : ServerAction +{ + public ChangePartnerServerAction() : base(BinaryLaneValues.ServerActionType.ChangePartner) { } + + [JsonPropertyName("partner_server_id")] + public long? PartnerServerId { get; init; } +} + +/// Enables or disables source-and-destination checking. +public sealed class ChangeSourceAndDestinationCheckServerAction : ServerAction +{ + public ChangeSourceAndDestinationCheckServerAction() : base(BinaryLaneValues.ServerActionType.ChangeSourceAndDestinationCheck) { } + + [JsonPropertyName("enabled")] + public bool Enabled { get; init; } +} + +/// Replaces a server's threshold-alert configuration. +public sealed class ChangeThresholdAlertsServerAction : ServerAction +{ + public ChangeThresholdAlertsServerAction() : base(BinaryLaneValues.ServerActionType.ChangeThresholdAlerts) { } + + [JsonPropertyName("threshold_alerts")] + public IReadOnlyList ThresholdAlerts { get; init; } = Array.Empty(); +} + +/// An advanced firewall rule supplied in a server-action request. +public sealed class AdvancedFirewallRuleRequest : BinaryLaneRequestModel +{ + [JsonPropertyName("source_addresses")] + public IReadOnlyList SourceAddresses { get; init; } = Array.Empty(); + + [JsonPropertyName("destination_addresses")] + public IReadOnlyList DestinationAddresses { get; init; } = Array.Empty(); + + [JsonPropertyName("destination_ports")] + public IReadOnlyList? DestinationPorts { get; init; } + + /// Provider protocol value, such as tcp. + [JsonPropertyName("protocol")] + public string Protocol { get; init; } = string.Empty; + + /// Provider action value, such as accept. + [JsonPropertyName("action")] + public string Action { get; init; } = string.Empty; + + [JsonPropertyName("description")] + public string? Description { get; init; } +} diff --git a/src/BinaryLane.Api/Models/ServerActionJsonConverter.cs b/src/BinaryLane.Api/Models/ServerActions/ServerActionJsonConverter.cs similarity index 97% rename from src/BinaryLane.Api/Models/ServerActionJsonConverter.cs rename to src/BinaryLane.Api/Models/ServerActions/ServerActionJsonConverter.cs index eda0cc2..86221cb 100644 --- a/src/BinaryLane.Api/Models/ServerActionJsonConverter.cs +++ b/src/BinaryLane.Api/Models/ServerActions/ServerActionJsonConverter.cs @@ -51,11 +51,11 @@ public sealed class ServerActionJsonConverter : JsonConverter public override void Write(Utf8JsonWriter writer, ServerAction value, JsonSerializerOptions options) { writer.WriteStartObject(); - writer.WriteString("type", value.Type); + writer.WriteString(ServerActionJsonNames.Type, value.Type); var writtenProperties = new HashSet(StringComparer.Ordinal) { - "type", + ServerActionJsonNames.Type, }; foreach (PropertyInfo property in GetPayloadProperties(value.GetType())) @@ -95,7 +95,7 @@ public sealed class ServerActionJsonConverter : JsonConverter private static string ReadType(JsonElement action) { - if (!action.TryGetProperty("type", out JsonElement typeElement) || + if (!action.TryGetProperty(ServerActionJsonNames.Type, out JsonElement typeElement) || typeElement.ValueKind != JsonValueKind.String || string.IsNullOrWhiteSpace(typeElement.GetString())) { @@ -156,7 +156,7 @@ public sealed class ServerActionJsonConverter : JsonConverter { var knownProperties = new HashSet(StringComparer.Ordinal) { - "type", + ServerActionJsonNames.Type, }; foreach (PropertyInfo property in GetPayloadProperties(action.GetType())) diff --git a/src/BinaryLane.Api/Models/ServerActions/ServerActionNetworkingModels.cs b/src/BinaryLane.Api/Models/ServerActions/ServerActionNetworkingModels.cs new file mode 100644 index 0000000..89146ca --- /dev/null +++ b/src/BinaryLane.Api/Models/ServerActions/ServerActionNetworkingModels.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace BinaryLane.Api.V2.Models; + +/// Enables or disables IPv6 for a server. +public sealed class ChangeIpv6ServerAction : ServerAction +{ + public ChangeIpv6ServerAction() : base(BinaryLaneValues.ServerActionType.ChangeIpv6) { } + + [JsonPropertyName("enabled")] + public bool Enabled { get; init; } +} + +/// Changes a server's IPv6 reverse nameservers. +public sealed class ChangeIpv6ReverseNameserversServerAction : ServerAction +{ + public ChangeIpv6ReverseNameserversServerAction() : base(BinaryLaneValues.ServerActionType.ChangeIpv6ReverseNameservers) { } + + [JsonPropertyName("ipv6_reverse_nameservers")] + public IReadOnlyList Ipv6ReverseNameservers { get; init; } = Array.Empty(); +} + +/// Moves a server onto or off a VPC network. +public sealed class ChangeNetworkServerAction : ServerAction +{ + public ChangeNetworkServerAction() : base(BinaryLaneValues.ServerActionType.ChangeNetwork) { } + + [JsonPropertyName("vpc_id")] + public long? VpcId { get; init; } +} + +/// Changes an IPv4 reverse name. +public sealed class ChangeReverseNameServerAction : ServerAction +{ + public ChangeReverseNameServerAction() : base(BinaryLaneValues.ServerActionType.ChangeReverseName) { } + + [JsonPropertyName("ipv4_address")] + public string Ipv4Address { get; init; } = string.Empty; + + [JsonPropertyName("reverse_name")] + public string? ReverseName { get; init; } +} + +/// Enables or disables a separate private network interface. +public sealed class ChangeSeparatePrivateNetworkInterfaceServerAction : ServerAction +{ + public ChangeSeparatePrivateNetworkInterfaceServerAction() : base(BinaryLaneValues.ServerActionType.ChangeSeparatePrivateNetworkInterface) { } + + [JsonPropertyName("enabled")] + public bool Enabled { get; init; } +} + +/// Changes a VPC IPv4 address on a server. +public sealed class ChangeVpcIpv4ServerAction : ServerAction +{ + public ChangeVpcIpv4ServerAction() : base(BinaryLaneValues.ServerActionType.ChangeVpcIpv4) { } + + [JsonPropertyName("current_ipv4_address")] + public string CurrentIpv4Address { get; init; } = string.Empty; + + [JsonPropertyName("new_ipv4_address")] + public string NewIpv4Address { get; init; } = string.Empty; +} + +/// Enables IPv6 on a server. +public sealed class EnableIpv6ServerAction : ServerAction +{ + public EnableIpv6ServerAction() : base(BinaryLaneValues.ServerActionType.EnableIpv6) { } +} diff --git a/src/BinaryLane.Api/Models/ServerActions/ServerActionOperationModels.cs b/src/BinaryLane.Api/Models/ServerActions/ServerActionOperationModels.cs new file mode 100644 index 0000000..8fa3aef --- /dev/null +++ b/src/BinaryLane.Api/Models/ServerActions/ServerActionOperationModels.cs @@ -0,0 +1,170 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace BinaryLane.Api.V2.Models; + +/// Disables SELinux in a compatible installed distribution. +public sealed class DisableSelinuxServerAction : ServerAction +{ + public DisableSelinuxServerAction() : base(BinaryLaneValues.ServerActionType.DisableSelinux) { } +} + +/// Checks whether a server is running. +public sealed class IsRunningServerAction : ServerAction +{ + public IsRunningServerAction() : base(BinaryLaneValues.ServerActionType.IsRunning) { } +} + +/// Resets a server password. +public sealed class PasswordResetServerAction : ServerAction +{ + public PasswordResetServerAction() : base(BinaryLaneValues.ServerActionType.PasswordReset) { } + + [JsonPropertyName("username")] + public string? Username { get; init; } + + /// Do not log this value. + [JsonPropertyName("password")] + public string? Password { get; init; } +} + +/// Pings a server. +public sealed class PingServerAction : ServerAction +{ + public PingServerAction() : base(BinaryLaneValues.ServerActionType.Ping) { } +} + +/// Power cycles a server. +public sealed class PowerCycleServerAction : ServerAction +{ + public PowerCycleServerAction() : base(BinaryLaneValues.ServerActionType.PowerCycle) { } +} + +/// Powers a server off. +public sealed class PowerOffServerAction : ServerAction +{ + public PowerOffServerAction() : base(BinaryLaneValues.ServerActionType.PowerOff) { } +} + +/// Powers a server on. +public sealed class PowerOnServerAction : ServerAction +{ + public PowerOnServerAction() : base(BinaryLaneValues.ServerActionType.PowerOn) { } +} + +/// Reboots a server. +public sealed class RebootServerAction : ServerAction +{ + public RebootServerAction() : base(BinaryLaneValues.ServerActionType.Reboot) { } +} + +/// Rebuilds a server from an image. +public sealed class RebuildServerAction : ServerAction +{ + public RebuildServerAction() : base(BinaryLaneValues.ServerActionType.Rebuild) { } + + /// An image ID or image slug. Omit to reuse the existing image. + [JsonPropertyName("image")] + public object? Image { get; init; } + + [JsonPropertyName("options")] + public ImageOptions? Options { get; init; } +} + +/// Renames a server. +public sealed class RenameServerAction : ServerAction +{ + public RenameServerAction() : base(BinaryLaneValues.ServerActionType.Rename) { } + + [JsonPropertyName("name")] + public string Name { get; init; } = string.Empty; +} + +/// Changes selected size options during a resize action. +public sealed class ChangeSizeOptionsRequest : BinaryLaneRequestModel +{ + [JsonPropertyName("daily_backups")] + public int? DailyBackups { get; init; } + + [JsonPropertyName("weekly_backups")] + public int? WeeklyBackups { get; init; } + + [JsonPropertyName("monthly_backups")] + public int? MonthlyBackups { get; init; } + + [JsonPropertyName("offsite_backups")] + public bool? OffsiteBackups { get; init; } + + [JsonPropertyName("ipv4_addresses")] + public int? Ipv4Addresses { get; init; } + + [JsonPropertyName("memory")] + public int? MemoryMegabytes { get; init; } + + [JsonPropertyName("disk")] + public int? DiskGigabytes { get; init; } + + [JsonPropertyName("transfer")] + public double? TransferGigabytes { get; init; } + + [JsonPropertyName("ipv4_addresses_to_remove")] + public IReadOnlyList? Ipv4AddressesToRemove { get; init; } +} + +/// Changes the source image selected by a resize operation. +public sealed class ChangeImage : BinaryLaneRequestModel +{ + /// An image ID or image slug. + [JsonPropertyName("image")] + public object? Image { get; init; } + + [JsonPropertyName("options")] + public ImageOptions? Options { get; init; } +} + +/// Changes licences selected by a resize operation. +public sealed class ChangeLicenses : BinaryLaneRequestModel +{ + [JsonPropertyName("licenses")] + public IReadOnlyList Licenses { get; init; } = Array.Empty(); +} + +/// Resizes a server. +public sealed class ResizeServerAction : ServerAction +{ + public ResizeServerAction() : base(BinaryLaneValues.ServerActionType.Resize) { } + + [JsonPropertyName("size")] + public string? Size { get; init; } + + [JsonPropertyName("options")] + public ChangeSizeOptionsRequest? Options { get; init; } + + [JsonPropertyName("change_image")] + public ChangeImage? ChangeImage { get; init; } + + [JsonPropertyName("change_licenses")] + public ChangeLicenses? ChangeLicenses { get; init; } + + [JsonPropertyName("pre_action_backup")] + public TakeBackupServerAction? PreActionBackup { get; init; } +} + +/// Requests a graceful shutdown. +public sealed class ShutdownServerAction : ServerAction +{ + public ShutdownServerAction() : base(BinaryLaneValues.ServerActionType.Shutdown) { } +} + +/// Reverses a scheduled server cancellation. +public sealed class UncancelServerAction : ServerAction +{ + public UncancelServerAction() : base(BinaryLaneValues.ServerActionType.Uncancel) { } +} + +/// Checks server uptime. +public sealed class UptimeServerAction : ServerAction +{ + public UptimeServerAction() : base(BinaryLaneValues.ServerActionType.Uptime) { } +} diff --git a/src/BinaryLane.Api/Models/Servers/ServerBackupAndInfrastructureModels.cs b/src/BinaryLane.Api/Models/Servers/ServerBackupAndInfrastructureModels.cs new file mode 100644 index 0000000..6b7c51a --- /dev/null +++ b/src/BinaryLane.Api/Models/Servers/ServerBackupAndInfrastructureModels.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace BinaryLane.Api.V2.Models; + +/// A scheduled backup window. +public sealed class BackupWindow : BinaryLaneDto +{ + [JsonPropertyName("start")] + public DateTimeOffset Start { get; init; } + + [JsonPropertyName("end")] + public DateTimeOffset End { get; init; } +} + +/// A server's configured backup schedule. +public sealed class BackupSettings : BinaryLaneDto +{ + [JsonPropertyName("backup_hour_of_day")] + public int BackupHourOfDay { get; init; } + + [JsonPropertyName("backup_day_of_week")] + public int BackupDayOfWeek { get; init; } + + [JsonPropertyName("backup_day_of_month")] + public int BackupDayOfMonth { get; init; } + + [JsonPropertyName("offsite_backup_settings")] + public OffsiteBackupSettings? OffsiteBackupSettings { get; init; } +} + +/// Offsite-backup configuration for a server. +public sealed class OffsiteBackupSettings : BinaryLaneDto +{ + [JsonPropertyName("use_custom_backup_location")] + public bool UseCustomBackupLocation { get; init; } + + [JsonPropertyName("offsite_backup_location")] + public string? OffsiteBackupLocation { get; init; } + + [JsonPropertyName("manage_offsite_copies")] + public bool? ManageOffsiteCopies { get; init; } +} + +/// The host backing a server. +public sealed class Host : BinaryLaneDto +{ + [JsonPropertyName("display_name")] + public string DisplayName { get; init; } = string.Empty; + + [JsonPropertyName("uptime_ms")] + public long? UptimeMilliseconds { get; init; } + + [JsonPropertyName("status_page")] + public string? StatusPage { get; init; } +} + +/// Metadata about a backup currently attached to a server. +public sealed class AttachedBackup : BinaryLaneDto +{ + [JsonPropertyName("id")] + public long Id { get; init; } + + [JsonPropertyName("disk_identifiers")] + public IReadOnlyList DiskIdentifiers { get; init; } = Array.Empty(); + + [JsonPropertyName("attached_at")] + public DateTimeOffset? AttachedAt { get; init; } + + [JsonPropertyName("attachment_expires")] + public DateTimeOffset? AttachmentExpires { get; init; } +} diff --git a/src/BinaryLane.Api/Models/Servers/ServerCapabilityModels.cs b/src/BinaryLane.Api/Models/Servers/ServerCapabilityModels.cs new file mode 100644 index 0000000..6c5d78b --- /dev/null +++ b/src/BinaryLane.Api/Models/Servers/ServerCapabilityModels.cs @@ -0,0 +1,158 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace BinaryLane.Api.V2.Models; + +/// Advanced virtual-machine features configured for a server. +public sealed class AdvancedServerFeatures : BinaryLaneDto +{ + [JsonPropertyName("processor_model")] + public long? ProcessorModel { get; init; } + + /// Provider virtual machine type. + [JsonPropertyName("machine_type")] + public string? MachineType { get; init; } + + /// Provider virtual video device. + [JsonPropertyName("video_device")] + public string VideoDevice { get; init; } = string.Empty; + + /// Provider advanced-feature values. + [JsonPropertyName("enabled_advanced_features")] + public IReadOnlyList EnabledAdvancedFeatures { get; init; } = Array.Empty(); +} + +/// Advanced server features currently available to the account. +public sealed class AvailableAdvancedServerFeatures : BinaryLaneDto +{ + [JsonPropertyName("processor_models")] + public IReadOnlyList ProcessorModels { get; init; } = Array.Empty(); + + [JsonPropertyName("machine_types")] + public IReadOnlyList MachineTypes { get; init; } = Array.Empty(); + + [JsonPropertyName("advanced_features")] + public IReadOnlyList AdvancedFeatures { get; init; } = Array.Empty(); +} + +/// An available processor model. +public sealed class ProcessorModel : BinaryLaneDto +{ + [JsonPropertyName("id")] + public long Id { get; init; } + + [JsonPropertyName("name")] + public string Name { get; init; } = string.Empty; + + [JsonPropertyName("description")] + public string? Description { get; init; } +} + +/// An advanced firewall rule applied to a server. +public sealed class AdvancedFirewallRule : BinaryLaneDto +{ + [JsonPropertyName("source_addresses")] + public IReadOnlyList SourceAddresses { get; init; } = Array.Empty(); + + [JsonPropertyName("destination_addresses")] + public IReadOnlyList DestinationAddresses { get; init; } = Array.Empty(); + + [JsonPropertyName("destination_ports")] + public IReadOnlyList? DestinationPorts { get; init; } + + /// Provider protocol value, such as tcp. + [JsonPropertyName("protocol")] + public string Protocol { get; init; } = string.Empty; + + /// Provider action value, such as accept. + [JsonPropertyName("action")] + public string Action { get; init; } = string.Empty; + + [JsonPropertyName("description")] + public string? Description { get; init; } +} + +/// An available server kernel. +public sealed class Kernel : BinaryLaneDto +{ + [JsonPropertyName("id")] + public long Id { get; init; } + + [JsonPropertyName("name")] + public string? Name { get; init; } + + [JsonPropertyName("version")] + public string? Version { get; init; } +} + +/// A configured server threshold alert. +public sealed class ThresholdAlert : BinaryLaneDto +{ + /// Provider alert type. + [JsonPropertyName("alert_type")] + public string AlertType { get; init; } = string.Empty; + + [JsonPropertyName("name")] + public string Name { get; init; } = string.Empty; + + [JsonPropertyName("unit")] + public string Unit { get; init; } = string.Empty; + + [JsonPropertyName("description")] + public string Description { get; init; } = string.Empty; + + [JsonPropertyName("enabled")] + public bool Enabled { get; init; } + + [JsonPropertyName("value")] + public int Value { get; init; } + + [JsonPropertyName("current_value")] + public int? CurrentValue { get; init; } + + [JsonPropertyName("last_raised")] + public DateTimeOffset? LastRaised { get; init; } + + [JsonPropertyName("last_cleared")] + public DateTimeOffset? LastCleared { get; init; } +} + +/// Software licensed on a server. +public sealed class LicensedSoftware : BinaryLaneDto +{ + [JsonPropertyName("software")] + public Software Software { get; init; } = new(); + + [JsonPropertyName("licence_count")] + public int LicenceCount { get; init; } + + [JsonPropertyName("incompatible")] + public bool Incompatible { get; init; } +} + +/// A browser console session for a server. +public sealed class ServerConsole : BinaryLaneDto +{ + [JsonPropertyName("iframe")] + public string Iframe { get; init; } = string.Empty; + + [JsonPropertyName("browser")] + public string Browser { get; init; } = string.Empty; + + [JsonPropertyName("width")] + public int Width { get; init; } + + [JsonPropertyName("height")] + public int Height { get; init; } + + [JsonPropertyName("expiry")] + public DateTimeOffset Expiry { get; init; } +} + +/// Server user-data retained by BinaryLane. +public sealed class UserData : BinaryLaneDto +{ + [JsonPropertyName("user_data")] + public string? Value { get; init; } +} diff --git a/src/BinaryLane.Api/Models/Servers/ServerModels.cs b/src/BinaryLane.Api/Models/Servers/ServerModels.cs new file mode 100644 index 0000000..1beb93a --- /dev/null +++ b/src/BinaryLane.Api/Models/Servers/ServerModels.cs @@ -0,0 +1,192 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace BinaryLane.Api.V2.Models; + +/// A BinaryLane server. +public sealed class Server : BinaryLaneDto +{ + [JsonPropertyName("id")] + public long Id { get; init; } + + [JsonPropertyName("name")] + public string Name { get; init; } = string.Empty; + + [JsonPropertyName("memory")] + public int MemoryMegabytes { get; init; } + + [JsonPropertyName("vcpus")] + public int Vcpus { get; init; } + + [JsonPropertyName("disk")] + public int DiskGigabytes { get; init; } + + [JsonPropertyName("vpc_id")] + public long? VpcId { get; init; } + + [JsonPropertyName("created_at")] + public DateTimeOffset CreatedAt { get; init; } + + /// Provider server status, for example active. + [JsonPropertyName("status")] + public string Status { get; init; } = string.Empty; + + [JsonPropertyName("backup_ids")] + public IReadOnlyList BackupIds { get; init; } = Array.Empty(); + + [JsonPropertyName("features")] + public IReadOnlyList Features { get; init; } = Array.Empty(); + + [JsonPropertyName("region")] + public Region Region { get; init; } = new(); + + [JsonPropertyName("image")] + public Image Image { get; init; } = new(); + + [JsonPropertyName("size")] + public Size Size { get; init; } = new(); + + [JsonPropertyName("size_slug")] + public string SizeSlug { get; init; } = string.Empty; + + [JsonPropertyName("selected_size_options")] + public SelectedSizeOptions? SelectedSizeOptions { get; init; } + + [JsonPropertyName("networks")] + public ServerNetworks Networks { get; init; } = new(); + + [JsonPropertyName("kernel")] + public Kernel? Kernel { get; init; } + + [JsonPropertyName("next_backup_window")] + public BackupWindow? NextBackupWindow { get; init; } + + [JsonPropertyName("disks")] + public IReadOnlyList Disks { get; init; } = Array.Empty(); + + [JsonPropertyName("backup_settings")] + public BackupSettings BackupSettings { get; init; } = new(); + + [JsonPropertyName("cancelled_at")] + public DateTimeOffset? CancelledAt { get; init; } + + [JsonPropertyName("failover_ips")] + public IReadOnlyList FailoverIps { get; init; } = Array.Empty(); + + [JsonPropertyName("host")] + public Host Host { get; init; } = new(); + + [JsonPropertyName("partner_id")] + public long? PartnerId { get; init; } + + [JsonPropertyName("password_change_supported")] + public bool PasswordChangeSupported { get; init; } + + [JsonPropertyName("permalink")] + public string? Permalink { get; init; } + + [JsonPropertyName("attached_backup")] + public AttachedBackup? AttachedBackup { get; init; } + + [JsonPropertyName("advanced_features")] + public AdvancedServerFeatures AdvancedFeatures { get; init; } = new(); + + [JsonPropertyName("is_under_maintenance")] + public bool? IsUnderMaintenance { get; init; } +} + +/// A server disk. +public sealed class Disk : BinaryLaneDto +{ + [JsonPropertyName("id")] + public long Id { get; init; } + + [JsonPropertyName("size_gigabytes")] + public double SizeGigabytes { get; init; } + + [JsonPropertyName("description")] + public string? Description { get; init; } + + [JsonPropertyName("primary")] + public bool Primary { get; init; } +} + +/// A server network assignment. +public sealed class ServerNetwork : BinaryLaneDto +{ + [JsonPropertyName("ip_address")] + public string IpAddress { get; init; } = string.Empty; + + /// May be represented by the provider as either a number or a string. + [JsonPropertyName("netmask")] + public object? Netmask { get; init; } + + [JsonPropertyName("gateway")] + public string? Gateway { get; init; } + + /// Provider network type, either public or private. + [JsonPropertyName("type")] + public string Type { get; init; } = string.Empty; + + [JsonPropertyName("reverse_name")] + public string? ReverseName { get; init; } + + [JsonPropertyName("nat_target")] + public string? NatTarget { get; init; } +} + +/// All IPv4/IPv6 network information associated with a server. +public sealed class ServerNetworks : BinaryLaneDto +{ + [JsonPropertyName("v4")] + public IReadOnlyList V4 { get; init; } = Array.Empty(); + + [JsonPropertyName("v6")] + public IReadOnlyList V6 { get; init; } = Array.Empty(); + + [JsonPropertyName("port_blocking")] + public bool PortBlocking { get; init; } + + [JsonPropertyName("separate_private_network_interface")] + public bool? SeparatePrivateNetworkInterface { get; init; } + + [JsonPropertyName("source_and_destination_check")] + public bool? SourceAndDestinationCheck { get; init; } + + [JsonPropertyName("recent_ddos")] + public bool RecentDdos { get; init; } + + [JsonPropertyName("ipv6_reverse_nameservers")] + public IReadOnlyList? Ipv6ReverseNameservers { get; init; } + + [JsonPropertyName("mac_address")] + public string MacAddress { get; init; } = string.Empty; +} + +public sealed class ServerResponse : BinaryLaneDto +{ + [JsonPropertyName("server")] + public Server Server { get; init; } = new(); +} + +public sealed class ServersResponse : BinaryLaneDto +{ + [JsonPropertyName("meta")] + public PageMeta Meta { get; init; } = new(); + + [JsonPropertyName("links")] + public PageLinks? Links { get; init; } + + [JsonPropertyName("servers")] + public IReadOnlyList Servers { get; init; } = Array.Empty(); +} + +public sealed class CreateServerResponse : BinaryLaneDto +{ + [JsonPropertyName("server")] + public Server Server { get; init; } = new(); + + [JsonPropertyName("links")] + public ActionsLinks Links { get; init; } = new(); +} diff --git a/src/BinaryLane.Api/Models/Servers/ServerRequestModels.cs b/src/BinaryLane.Api/Models/Servers/ServerRequestModels.cs new file mode 100644 index 0000000..b608f9d --- /dev/null +++ b/src/BinaryLane.Api/Models/Servers/ServerRequestModels.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace BinaryLane.Api.V2.Models; + +/// Options selected while creating or rebuilding a server image. +public sealed class ImageOptions : BinaryLaneRequestModel +{ + [JsonPropertyName("name")] + public string? Name { get; init; } + + /// Each identifier may be either an SSH key ID or a public-key fingerprint. + [JsonPropertyName("ssh_keys")] + public IReadOnlyList? SshKeys { get; init; } + + /// Do not log user-data; it can contain secrets. + [JsonPropertyName("user_data")] + public string? UserData { get; init; } + + /// Do not log this value. + [JsonPropertyName("password")] + public string? Password { get; init; } +} + +/// A requested software licence allocation. +public sealed class License : BinaryLaneRequestModel +{ + [JsonPropertyName("software_id")] + public long SoftwareId { get; init; } + + [JsonPropertyName("count")] + public int Count { get; init; } +} + +/// Creates a new BinaryLane server. +public sealed class CreateServerRequest : BinaryLaneRequestModel +{ + [JsonPropertyName("name")] + public string? Name { get; init; } + + [JsonPropertyName("backups")] + public bool? Backups { get; init; } + + [JsonPropertyName("ipv6")] + public bool? Ipv6 { get; init; } + + [JsonPropertyName("size")] + public string Size { get; init; } = string.Empty; + + /// An image ID or provider image slug. + [JsonPropertyName("image")] + public object Image { get; init; } = string.Empty; + + [JsonPropertyName("region")] + public string Region { get; init; } = string.Empty; + + [JsonPropertyName("vpc_id")] + public long? VpcId { get; init; } + + [JsonPropertyName("vpc_ipv4_address")] + public string? VpcIpv4Address { get; init; } + + /// Each entry may be an SSH key ID or fingerprint. + [JsonPropertyName("ssh_keys")] + public IReadOnlyList? SshKeys { get; init; } + + [JsonPropertyName("options")] + public SizeOptionsRequest? Options { get; init; } + + [JsonPropertyName("licenses")] + public IReadOnlyList? Licenses { get; init; } + + /// Do not log user-data; it may contain secrets. + [JsonPropertyName("user_data")] + public string? UserData { get; init; } + + [JsonPropertyName("port_blocking")] + public bool? PortBlocking { get; init; } + + [JsonPropertyName("separate_private_network_interface")] + public bool? SeparatePrivateNetworkInterface { get; init; } + + /// Do not log this value. + [JsonPropertyName("password")] + public string? Password { get; init; } +} + +/// Updates threshold-alert configuration. +public sealed class ThresholdAlertRequest : BinaryLaneRequestModel +{ + /// Provider alert type. + [JsonPropertyName("alert_type")] + public string AlertType { get; init; } = string.Empty; + + [JsonPropertyName("enabled")] + public bool? Enabled { get; init; } + + [JsonPropertyName("value")] + public int? Value { get; init; } +} diff --git a/src/BinaryLane.Api/Models/Servers/ServerResponseModels.cs b/src/BinaryLane.Api/Models/Servers/ServerResponseModels.cs new file mode 100644 index 0000000..d8d820e --- /dev/null +++ b/src/BinaryLane.Api/Models/Servers/ServerResponseModels.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace BinaryLane.Api.V2.Models; + +public sealed class AdvancedFirewallRulesResponse : BinaryLaneDto +{ + [JsonPropertyName("firewall_rules")] + public IReadOnlyList FirewallRules { get; init; } = Array.Empty(); +} + +public sealed class AvailableAdvancedServerFeaturesResponse : BinaryLaneDto +{ + [JsonPropertyName("available_advanced_server_features")] + public AvailableAdvancedServerFeatures AvailableAdvancedServerFeatures { get; init; } = new(); +} + +public sealed class BackupsResponse : BinaryLaneDto +{ + [JsonPropertyName("meta")] + public PageMeta Meta { get; init; } = new(); + + [JsonPropertyName("links")] + public PageLinks? Links { get; init; } + + [JsonPropertyName("backups")] + public IReadOnlyList Backups { get; init; } = Array.Empty(); +} + +public sealed class KernelsResponse : BinaryLaneDto +{ + [JsonPropertyName("meta")] + public PageMeta Meta { get; init; } = new(); + + [JsonPropertyName("links")] + public PageLinks? Links { get; init; } + + [JsonPropertyName("kernels")] + public IReadOnlyList Kernels { get; init; } = Array.Empty(); +} + +public sealed class SnapshotsResponse : BinaryLaneDto +{ + [JsonPropertyName("meta")] + public PageMeta Meta { get; init; } = new(); + + [JsonPropertyName("links")] + public PageLinks? Links { get; init; } + + [JsonPropertyName("snapshots")] + public IReadOnlyList Snapshots { get; init; } = Array.Empty(); +} + +public sealed class ThresholdAlertsResponse : BinaryLaneDto +{ + [JsonPropertyName("threshold_alerts")] + public IReadOnlyList ThresholdAlerts { get; init; } = Array.Empty(); +} + +public sealed class CurrentServerAlertsResponse : BinaryLaneDto +{ + [JsonPropertyName("server_ids")] + public IReadOnlyList ServerIds { get; init; } = Array.Empty(); +} + +public sealed class LicensedSoftwaresResponse : BinaryLaneDto +{ + [JsonPropertyName("meta")] + public PageMeta Meta { get; init; } = new(); + + [JsonPropertyName("links")] + public PageLinks? Links { get; init; } + + [JsonPropertyName("licensed_software")] + public IReadOnlyList LicensedSoftware { get; init; } = Array.Empty(); +} + +public sealed class ServerConsoleResponse : BinaryLaneDto +{ + [JsonPropertyName("console")] + public ServerConsole Console { get; init; } = new(); +} diff --git a/src/BinaryLane.Api/Models/Sizes/SizeModels.cs b/src/BinaryLane.Api/Models/Sizes/SizeModels.cs new file mode 100644 index 0000000..53e55e5 --- /dev/null +++ b/src/BinaryLane.Api/Models/Sizes/SizeModels.cs @@ -0,0 +1,209 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace BinaryLane.Api.V2.Models; + +/// A provider server size and its available customisation options. +public sealed class Size : BinaryLaneDto +{ + [JsonPropertyName("slug")] + public string Slug { get; init; } = string.Empty; + + [JsonPropertyName("description")] + public string? Description { get; init; } + + [JsonPropertyName("cpu_description")] + public string? CpuDescription { get; init; } + + [JsonPropertyName("storage_description")] + public string? StorageDescription { get; init; } + + [JsonPropertyName("size_type")] + public SizeType SizeType { get; init; } = new(); + + [JsonPropertyName("available")] + public bool Available { get; init; } + + [JsonPropertyName("regions")] + public IReadOnlyList Regions { get; init; } = Array.Empty(); + + [JsonPropertyName("regions_out_of_stock")] + public IReadOnlyList? RegionsOutOfStock { get; init; } + + [JsonPropertyName("price_monthly")] + public double PriceMonthly { get; init; } + + [JsonPropertyName("price_hourly")] + public double PriceHourly { get; init; } + + [JsonPropertyName("disk")] + public int DiskGigabytes { get; init; } + + [JsonPropertyName("memory")] + public int MemoryMegabytes { get; init; } + + [JsonPropertyName("transfer")] + public double TransferGigabytes { get; init; } + + [JsonPropertyName("excess_transfer_cost_per_gigabyte")] + public double ExcessTransferCostPerGigabyte { get; init; } + + [JsonPropertyName("vcpus")] + public int Vcpus { get; init; } + + [JsonPropertyName("vcpu_units")] + public string VcpuUnits { get; init; } = string.Empty; + + [JsonPropertyName("options")] + public SizeOptions Options { get; init; } = new(); +} + +/// The provider's category for a server size. +public sealed class SizeType : BinaryLaneDto +{ + [JsonPropertyName("slug")] + public string Slug { get; init; } = string.Empty; + + [JsonPropertyName("name")] + public string Name { get; init; } = string.Empty; + + [JsonPropertyName("description")] + public string? Description { get; init; } +} + +/// Configurable bounds and costs associated with a server size. +public sealed class SizeOptions : BinaryLaneDto +{ + [JsonPropertyName("disk_min")] + public int DiskMinGigabytes { get; init; } + + [JsonPropertyName("disk_max")] + public int DiskMaxGigabytes { get; init; } + + [JsonPropertyName("disk_cost_per_additional_gigabyte")] + public double DiskCostPerAdditionalGigabyte { get; init; } + + [JsonPropertyName("restricted_disk_values")] + public IReadOnlyList? RestrictedDiskValues { get; init; } + + [JsonPropertyName("memory_max")] + public int MemoryMaxMegabytes { get; init; } + + [JsonPropertyName("memory_cost_per_additional_megabyte")] + public double MemoryCostPerAdditionalMegabyte { get; init; } + + [JsonPropertyName("transfer_max")] + public double TransferMaxGigabytes { get; init; } + + [JsonPropertyName("transfer_cost_per_additional_gigabyte")] + public double TransferCostPerAdditionalGigabyte { get; init; } + + [JsonPropertyName("ipv4_addresses_max")] + public int Ipv4AddressesMax { get; init; } + + [JsonPropertyName("ipv4_addresses_cost_per_address")] + public double Ipv4AddressesCostPerAddress { get; init; } + + [JsonPropertyName("discount_for_no_public_ipv4")] + public double DiscountForNoPublicIpv4 { get; init; } + + [JsonPropertyName("daily_backups")] + public int DailyBackups { get; init; } + + [JsonPropertyName("weekly_backups")] + public int WeeklyBackups { get; init; } + + [JsonPropertyName("monthly_backups")] + public int MonthlyBackups { get; init; } + + [JsonPropertyName("backups_cost_per_backup_per_gigabyte")] + public double BackupsCostPerBackupPerGigabyte { get; init; } + + [JsonPropertyName("offsite_backups_cost_per_gigabyte")] + public double OffsiteBackupsCostPerGigabyte { get; init; } + + [JsonPropertyName("offsite_backup_frequency_cost")] + public OffsiteBackupFrequencyCost OffsiteBackupFrequencyCost { get; init; } = new(); +} + +/// The backup frequency costs published for a size. +public sealed class OffsiteBackupFrequencyCost : BinaryLaneDto +{ + [JsonPropertyName("daily_per_gigabyte")] + public double DailyPerGigabyte { get; init; } + + [JsonPropertyName("weekly_per_gigabyte")] + public double WeeklyPerGigabyte { get; init; } + + [JsonPropertyName("monthly_per_gigabyte")] + public double MonthlyPerGigabyte { get; init; } +} + +/// The options selected for an individual server. +public sealed class SelectedSizeOptions : BinaryLaneDto +{ + [JsonPropertyName("daily_backups")] + public int DailyBackups { get; init; } + + [JsonPropertyName("weekly_backups")] + public int WeeklyBackups { get; init; } + + [JsonPropertyName("monthly_backups")] + public int MonthlyBackups { get; init; } + + [JsonPropertyName("offsite_backups")] + public bool OffsiteBackups { get; init; } + + [JsonPropertyName("ipv4_addresses")] + public int Ipv4Addresses { get; init; } + + [JsonPropertyName("memory")] + public int MemoryMegabytes { get; init; } + + [JsonPropertyName("disk")] + public int DiskGigabytes { get; init; } + + [JsonPropertyName("transfer")] + public double TransferGigabytes { get; init; } +} + +/// Customisable options for a server size. +public sealed class SizeOptionsRequest : BinaryLaneRequestModel +{ + [JsonPropertyName("daily_backups")] + public int? DailyBackups { get; init; } + + [JsonPropertyName("weekly_backups")] + public int? WeeklyBackups { get; init; } + + [JsonPropertyName("monthly_backups")] + public int? MonthlyBackups { get; init; } + + [JsonPropertyName("offsite_backups")] + public bool? OffsiteBackups { get; init; } + + [JsonPropertyName("ipv4_addresses")] + public int? Ipv4Addresses { get; init; } + + [JsonPropertyName("memory")] + public int? MemoryMegabytes { get; init; } + + [JsonPropertyName("disk")] + public int? DiskGigabytes { get; init; } + + [JsonPropertyName("transfer")] + public double? TransferGigabytes { get; init; } +} + +public sealed class SizesResponse : BinaryLaneDto +{ + [JsonPropertyName("meta")] + public PageMeta Meta { get; init; } = new(); + + [JsonPropertyName("links")] + public PageLinks? Links { get; init; } + + [JsonPropertyName("sizes")] + public IReadOnlyList Sizes { get; init; } = Array.Empty(); +} diff --git a/src/BinaryLane.Api/Models/Software/SoftwareModels.cs b/src/BinaryLane.Api/Models/Software/SoftwareModels.cs new file mode 100644 index 0000000..1bc0543 --- /dev/null +++ b/src/BinaryLane.Api/Models/Software/SoftwareModels.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace BinaryLane.Api.V2.Models; + +/// A software product that can be licensed on BinaryLane servers. +public sealed class Software : BinaryLaneDto +{ + [JsonPropertyName("id")] + public long Id { get; init; } + + [JsonPropertyName("enabled")] + public bool Enabled { get; init; } + + [JsonPropertyName("name")] + public string Name { get; init; } = string.Empty; + + [JsonPropertyName("description")] + public string Description { get; init; } = string.Empty; + + [JsonPropertyName("cost_per_licence_per_month")] + public double CostPerLicencePerMonth { get; init; } + + [JsonPropertyName("minimum_licence_count")] + public int MinimumLicenceCount { get; init; } + + [JsonPropertyName("maximum_licence_count")] + public int MaximumLicenceCount { get; init; } + + [JsonPropertyName("licence_step_count")] + public int LicenceStepCount { get; init; } + + [JsonPropertyName("group")] + public string? Group { get; init; } + + [JsonPropertyName("supported_operating_systems")] + public IReadOnlyList SupportedOperatingSystems { get; init; } = Array.Empty(); +} + +public sealed class SoftwareResponse : BinaryLaneDto +{ + [JsonPropertyName("software")] + public Software Software { get; init; } = new(); +} + +public sealed class SoftwaresResponse : BinaryLaneDto +{ + [JsonPropertyName("meta")] + public PageMeta Meta { get; init; } = new(); + + [JsonPropertyName("links")] + public PageLinks? Links { get; init; } + + [JsonPropertyName("software")] + public IReadOnlyList Software { get; init; } = Array.Empty(); +} diff --git a/src/BinaryLane.Api/Models/SshKeys/SshKeyModels.cs b/src/BinaryLane.Api/Models/SshKeys/SshKeyModels.cs new file mode 100644 index 0000000..96bf3c3 --- /dev/null +++ b/src/BinaryLane.Api/Models/SshKeys/SshKeyModels.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace BinaryLane.Api.V2.Models; + +/// An SSH public key owned by the authenticated account. +public sealed class SshKey : BinaryLaneDto +{ + [JsonPropertyName("id")] + public long Id { get; init; } + + [JsonPropertyName("fingerprint")] + public string Fingerprint { get; init; } = string.Empty; + + [JsonPropertyName("public_key")] + public string PublicKey { get; init; } = string.Empty; + + [JsonPropertyName("name")] + public string? Name { get; init; } + + [JsonPropertyName("default")] + public bool IsDefault { get; init; } +} + +public sealed class SshKeyResponse : BinaryLaneDto +{ + [JsonPropertyName("ssh_key")] + public SshKey SshKey { get; init; } = new(); +} + +public sealed class SshKeysResponse : BinaryLaneDto +{ + [JsonPropertyName("meta")] + public PageMeta Meta { get; init; } = new(); + + [JsonPropertyName("links")] + public PageLinks? Links { get; init; } + + [JsonPropertyName("ssh_keys")] + public IReadOnlyList SshKeys { get; init; } = Array.Empty(); +} diff --git a/src/BinaryLane.Api/Models/SshKeys/SshKeyRequestModels.cs b/src/BinaryLane.Api/Models/SshKeys/SshKeyRequestModels.cs new file mode 100644 index 0000000..a65b065 --- /dev/null +++ b/src/BinaryLane.Api/Models/SshKeys/SshKeyRequestModels.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace BinaryLane.Api.V2.Models; + +/// Creates an SSH key. +public sealed class SshKeyRequest : BinaryLaneRequestModel +{ + [JsonPropertyName("public_key")] + public string PublicKey { get; init; } = string.Empty; + + [JsonPropertyName("name")] + public string Name { get; init; } = string.Empty; + + [JsonPropertyName("default")] + public bool? IsDefault { get; init; } +} + +/// Updates an SSH key. +public sealed class UpdateSshKeyRequest : BinaryLaneRequestModel +{ + [JsonPropertyName("name")] + public string Name { get; init; } = string.Empty; + + [JsonPropertyName("default")] + public bool? IsDefault { get; init; } +} diff --git a/src/BinaryLane.Api/Models/Values/BinaryLaneValues.AccountAndActions.cs b/src/BinaryLane.Api/Models/Values/BinaryLaneValues.AccountAndActions.cs new file mode 100644 index 0000000..37fdc5c --- /dev/null +++ b/src/BinaryLane.Api/Models/Values/BinaryLaneValues.AccountAndActions.cs @@ -0,0 +1,94 @@ +namespace BinaryLane.Api.V2.Models; + +public static partial class BinaryLaneValues +{ + public static class AccountStatus + { + public const string Incomplete = "incomplete"; + public const string Active = "active"; + public const string Warning = "warning"; + public const string Locked = "locked"; + } + + public static class ActionStatus + { + public const string InProgress = "in-progress"; + public const string Completed = "completed"; + public const string Errored = "errored"; + } + + public static class ResourceType + { + public const string Server = "server"; + public const string LoadBalancer = "load-balancer"; + public const string SshKey = "ssh-key"; + public const string Vpc = "vpc"; + public const string Image = "image"; + public const string RegisteredDomainName = "registered-domain-name"; + } + + public static class PaymentMethod + { + public const string CreditCard = "credit-card"; + public const string Paypal = "paypal"; + } + + public static class TaxCodeType + { + public const string None = "none"; + public const string Scalar = "scalar"; + } + + public static class UserInteractionType + { + public const string ContinueAfterPingFailure = "continue-after-ping-failure"; + public const string AllowUncleanPowerOff = "allow-unclean-power-off"; + } + + /// Discriminator values for payloads. + public static class ServerActionType + { + public const string AddDisk = "add_disk"; + public const string AttachBackup = "attach_backup"; + public const string ChangeAdvancedFeatures = "change_advanced_features"; + public const string ChangeAdvancedFirewallRules = "change_advanced_firewall_rules"; + public const string ChangeBackupSchedule = "change_backup_schedule"; + public const string ChangeIpv6 = "change_ipv6"; + public const string ChangeIpv6ReverseNameservers = "change_ipv6_reverse_nameservers"; + public const string ChangeKernel = "change_kernel"; + public const string ChangeManageOffsiteBackupCopies = "change_manage_offsite_backup_copies"; + public const string ChangeNetwork = "change_network"; + public const string ChangeOffsiteBackupLocation = "change_offsite_backup_location"; + public const string ChangePartner = "change_partner"; + public const string ChangePortBlocking = "change_port_blocking"; + public const string ChangeRegion = "change_region"; + public const string ChangeReverseName = "change_reverse_name"; + public const string ChangeSeparatePrivateNetworkInterface = "change_separate_private_network_interface"; + public const string ChangeSourceAndDestinationCheck = "change_source_and_destination_check"; + public const string ChangeThresholdAlerts = "change_threshold_alerts"; + public const string ChangeVpcIpv4 = "change_vpc_ipv4"; + public const string CloneUsingBackup = "clone_using_backup"; + public const string DeleteDisk = "delete_disk"; + public const string DetachBackup = "detach_backup"; + public const string DisableBackups = "disable_backups"; + public const string DisableSelinux = "disable_selinux"; + public const string EnableBackups = "enable_backups"; + public const string EnableIpv6 = "enable_ipv6"; + public const string IsRunning = "is_running"; + public const string PasswordReset = "password_reset"; + public const string Ping = "ping"; + public const string PowerCycle = "power_cycle"; + public const string PowerOff = "power_off"; + public const string PowerOn = "power_on"; + public const string Reboot = "reboot"; + public const string Rebuild = "rebuild"; + public const string Rename = "rename"; + public const string Resize = "resize"; + public const string ResizeDisk = "resize_disk"; + public const string Restore = "restore"; + public const string Shutdown = "shutdown"; + public const string TakeBackup = "take_backup"; + public const string Uncancel = "uncancel"; + public const string Uptime = "uptime"; + } +} diff --git a/src/BinaryLane.Api/Models/Values/BinaryLaneValues.ImagesAndCatalog.cs b/src/BinaryLane.Api/Models/Values/BinaryLaneValues.ImagesAndCatalog.cs new file mode 100644 index 0000000..9fc30ee --- /dev/null +++ b/src/BinaryLane.Api/Models/Values/BinaryLaneValues.ImagesAndCatalog.cs @@ -0,0 +1,42 @@ +namespace BinaryLane.Api.V2.Models; + +public static partial class BinaryLaneValues +{ + public static class ImageType + { + public const string Custom = "custom"; + public const string Snapshot = "snapshot"; + public const string Backup = "backup"; + } + + public static class ImageStatus + { + public const string New = "NEW"; + public const string Available = "available"; + public const string Pending = "pending"; + public const string Deleted = "deleted"; + } + + public static class ImageQueryType + { + public const string Distribution = "distribution"; + public const string Backup = "backup"; + } + + public static class DistributionFeature + { + public const string Ssh = "ssh"; + public const string RemoteDesktop = "remote-desktop"; + public const string UserData = "user-data"; + } + + public static class DataInterval + { + public const string FiveMinute = "five-minute"; + public const string HalfHour = "half-hour"; + public const string FourHour = "four-hour"; + public const string Day = "day"; + public const string Week = "week"; + public const string Month = "month"; + } +} diff --git a/src/BinaryLane.Api/Models/Values/BinaryLaneValues.NetworkingAndDns.cs b/src/BinaryLane.Api/Models/Values/BinaryLaneValues.NetworkingAndDns.cs new file mode 100644 index 0000000..738a143 --- /dev/null +++ b/src/BinaryLane.Api/Models/Values/BinaryLaneValues.NetworkingAndDns.cs @@ -0,0 +1,69 @@ +namespace BinaryLane.Api.V2.Models; + +public static partial class BinaryLaneValues +{ + public static class NetworkType + { + public const string Private = "private"; + public const string Public = "public"; + } + + public static class DomainRecordType + { + public const string A = "A"; + public const string Aaaa = "AAAA"; + public const string Caa = "CAA"; + public const string Cname = "CNAME"; + public const string Mx = "MX"; + public const string Ns = "NS"; + public const string Soa = "SOA"; + public const string Srv = "SRV"; + public const string Txt = "TXT"; + } + + public static class LoadBalancerStatus + { + public const string New = "new"; + public const string Active = "active"; + public const string Errored = "errored"; + } + + public static class LoadBalancerRuleProtocol + { + public const string Http = "http"; + public const string Https = "https"; + } + + public static class HealthCheckProtocol + { + public const string Http = "http"; + public const string Https = "https"; + public const string Both = "both"; + } + + public static class AdvancedFirewallRuleProtocol + { + public const string All = "all"; + public const string Icmp = "icmp"; + public const string Tcp = "tcp"; + public const string Udp = "udp"; + } + + public static class AdvancedFirewallRuleAction + { + public const string Drop = "drop"; + public const string Accept = "accept"; + } + + public static class ThresholdAlertType + { + public const string Cpu = "cpu"; + public const string StorageRequests = "storage-requests"; + public const string NetworkIncoming = "network-incoming"; + public const string NetworkOutgoing = "network-outgoing"; + public const string DataTransferUsed = "data-transfer-used"; + public const string StorageUsed = "storage-used"; + public const string MemoryUsed = "memory-used"; + public const string LockedBackupSlots = "locked-backup-slots"; + } +} diff --git a/src/BinaryLane.Api/Models/Values/BinaryLaneValues.ServerAndBackup.cs b/src/BinaryLane.Api/Models/Values/BinaryLaneValues.ServerAndBackup.cs new file mode 100644 index 0000000..fd2a291 --- /dev/null +++ b/src/BinaryLane.Api/Models/Values/BinaryLaneValues.ServerAndBackup.cs @@ -0,0 +1,72 @@ +namespace BinaryLane.Api.V2.Models; + +public static partial class BinaryLaneValues +{ + public static class ServerStatus + { + public const string New = "new"; + public const string Active = "active"; + public const string Archive = "archive"; + + public const string ProviderFalse = "False"; + } + + public static class BackupSlot + { + public const string Daily = "daily"; + public const string Weekly = "weekly"; + public const string Monthly = "monthly"; + public const string Temporary = "temporary"; + } + + public static class BackupReplacementStrategy + { + public const string None = "none"; + public const string Specified = "specified"; + public const string Oldest = "oldest"; + public const string Newest = "newest"; + } + + public static class PasswordRecoveryType + { + public const string Manual = "manual"; + public const string OfflineClear = "offline-clear"; + public const string OfflineChange = "offline-change"; + public const string OnlineChange = "online-change"; + } + + public static class AdvancedFeature + { + public const string EmulatedHyperV = "emulated-hyperv"; + public const string EmulatedDevices = "emulated-devices"; + public const string NestedVirt = "nested-virt"; + public const string DriverDisk = "driver-disk"; + public const string UnsetUuid = "unset-uuid"; + public const string LocalRtc = "local-rtc"; + public const string EmulatedTpm = "emulated-tpm"; + public const string CloudInit = "cloud-init"; + public const string QemuGuestAgent = "qemu-guest-agent"; + public const string UefiBoot = "uefi-boot"; + } + + public static class VideoDevice + { + public const string CirrusLogic = "cirrus-logic"; + public const string Standard = "standard"; + public const string Virtio = "virtio"; + public const string VirtioWide = "virtio-wide"; + } + + public static class VmMachineType + { + public const string PcI440Fx1Point5 = "pc_i440fx_1point5"; + public const string PcI440Fx2Point11 = "pc_i440fx_2point11"; + public const string PcI440Fx4Point1 = "pc_i440fx_4point1"; + public const string PcI440Fx4Point2 = "pc_i440fx_4point2"; + public const string PcI440Fx5Point0 = "pc_i440fx_5point0"; + public const string PcI440Fx5Point1 = "pc_i440fx_5point1"; + public const string PcI440Fx7Point2 = "pc_i440fx_7point2"; + public const string PcI440Fx7Point2Point1 = "pc_i440fx_7point2point1"; + public const string PcI440Fx8Point2 = "pc_i440fx_8point2"; + } +} diff --git a/src/BinaryLane.Api/Models/Values/BinaryLaneValues.cs b/src/BinaryLane.Api/Models/Values/BinaryLaneValues.cs new file mode 100644 index 0000000..9242b85 --- /dev/null +++ b/src/BinaryLane.Api/Models/Values/BinaryLaneValues.cs @@ -0,0 +1,14 @@ +namespace BinaryLane.Api.V2.Models; + +/// +/// Known string values in the BinaryLane v2 contract. +/// +/// +/// The API remains a developer preview. Public DTOs use strings rather than +/// closed C# enums so an upstream value added after an SDK release remains +/// readable. These constants make documented values discoverable without +/// removing that forward compatibility. +/// +public static partial class BinaryLaneValues +{ +} diff --git a/src/BinaryLane.Api/Models/Vpcs/VpcModels.cs b/src/BinaryLane.Api/Models/Vpcs/VpcModels.cs new file mode 100644 index 0000000..7bf1a2c --- /dev/null +++ b/src/BinaryLane.Api/Models/Vpcs/VpcModels.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace BinaryLane.Api.V2.Models; + +/// A virtual private cloud. +public sealed class Vpc : BinaryLaneDto +{ + [JsonPropertyName("id")] + public long Id { get; init; } + + [JsonPropertyName("name")] + public string Name { get; init; } = string.Empty; + + [JsonPropertyName("ip_range")] + public string IpRange { get; init; } = string.Empty; + + [JsonPropertyName("route_entries")] + public IReadOnlyList RouteEntries { get; init; } = Array.Empty(); +} + +/// A route within a VPC. +public sealed class RouteEntry : BinaryLaneDto +{ + [JsonPropertyName("router")] + public string Router { get; init; } = string.Empty; + + [JsonPropertyName("destination")] + public string Destination { get; init; } = string.Empty; + + [JsonPropertyName("description")] + public string? Description { get; init; } +} + +/// A resource connected to a VPC. +public sealed class VpcMember : BinaryLaneDto +{ + [JsonPropertyName("name")] + public string Name { get; init; } = string.Empty; + + /// Provider resource type. + [JsonPropertyName("resource_type")] + public string ResourceType { get; init; } = string.Empty; + + /// The provider documents this as a string, unlike action resource identifiers. + [JsonPropertyName("resource_id")] + public string ResourceId { get; init; } = string.Empty; + + [JsonPropertyName("created_at")] + public DateTimeOffset? CreatedAt { get; init; } +} + +public sealed class VpcResponse : BinaryLaneDto +{ + [JsonPropertyName("vpc")] + public Vpc Vpc { get; init; } = new(); +} + +public sealed class VpcsResponse : BinaryLaneDto +{ + [JsonPropertyName("meta")] + public PageMeta Meta { get; init; } = new(); + + [JsonPropertyName("links")] + public PageLinks? Links { get; init; } + + [JsonPropertyName("vpcs")] + public IReadOnlyList Vpcs { get; init; } = Array.Empty(); +} + +public sealed class VpcMembersResponse : BinaryLaneDto +{ + [JsonPropertyName("meta")] + public PageMeta Meta { get; init; } = new(); + + [JsonPropertyName("links")] + public PageLinks? Links { get; init; } + + [JsonPropertyName("members")] + public IReadOnlyList Members { get; init; } = Array.Empty(); +} diff --git a/src/BinaryLane.Api/Models/Vpcs/VpcRequestModels.cs b/src/BinaryLane.Api/Models/Vpcs/VpcRequestModels.cs new file mode 100644 index 0000000..7ef7e47 --- /dev/null +++ b/src/BinaryLane.Api/Models/Vpcs/VpcRequestModels.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace BinaryLane.Api.V2.Models; + +/// Creates a new VPC. +public sealed class CreateVpcRequest : BinaryLaneRequestModel +{ + [JsonPropertyName("name")] + public string Name { get; init; } = string.Empty; + + [JsonPropertyName("route_entries")] + public IReadOnlyList? RouteEntries { get; init; } + + [JsonPropertyName("ip_range")] + public string? IpRange { get; init; } +} + +/// Replaces VPC configuration. Omitted properties are cleared by the provider. +public sealed class UpdateVpcRequest : BinaryLaneRequestModel +{ + [JsonPropertyName("name")] + public string Name { get; init; } = string.Empty; + + [JsonPropertyName("route_entries")] + public IReadOnlyList? RouteEntries { get; init; } +} + +/// Partially updates VPC configuration. +public sealed class PatchVpcRequest : BinaryLaneRequestModel +{ + [JsonPropertyName("name")] + public string? Name { get; init; } + + [JsonPropertyName("route_entries")] + public IReadOnlyList? RouteEntries { get; init; } +} + +/// A VPC route entry supplied in a create or update request. +public sealed class RouteEntryRequest : BinaryLaneRequestModel +{ + [JsonPropertyName("router")] + public string Router { get; init; } = string.Empty; + + [JsonPropertyName("destination")] + public string Destination { get; init; } = string.Empty; + + [JsonPropertyName("description")] + public string? Description { get; init; } +} diff --git a/src/BinaryLane.Api/Resources/AccountApi.cs b/src/BinaryLane.Api/Resources/AccountApi.cs new file mode 100644 index 0000000..abd7eaa --- /dev/null +++ b/src/BinaryLane.Api/Resources/AccountApi.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using BinaryLane.Api.V2.Http; +using BinaryLane.Api.V2.Models; +using BinaryLane.Api.V2.Pagination; + +namespace BinaryLane.Api.V2.Resources; + +/// Reads information about the authenticated account. +public interface IAccountApi +{ + /// Gets the current account. + Task GetAsync(CancellationToken cancellationToken = default); + + /// Gets the untyped account response for forward compatibility. + Task GetRawAsync(CancellationToken cancellationToken = default); +} + +/// +public sealed class AccountApi : BinaryLaneResourceBase, IAccountApi +{ + /// Initializes the account resource. + public AccountApi(IBinaryLaneApiExecutor executor, BinaryLaneJsonSerializerOptions json) + : base(executor, json) + { + } + + /// + public Task GetAsync(CancellationToken cancellationToken = default) => + GetItemAsync("v2/account", "account", cancellationToken); + + /// + public Task GetRawAsync(CancellationToken cancellationToken = default) => + base.GetRawAsync("v2/account", null, cancellationToken); +} diff --git a/src/BinaryLane.Api/Resources/ActionsApi.cs b/src/BinaryLane.Api/Resources/ActionsApi.cs new file mode 100644 index 0000000..a8ddd23 --- /dev/null +++ b/src/BinaryLane.Api/Resources/ActionsApi.cs @@ -0,0 +1,99 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using BinaryLane.Api.V2.Http; +using BinaryLane.Api.V2.Models; +using BinaryLane.Api.V2.Pagination; + +namespace BinaryLane.Api.V2.Resources; + +/// Reads and waits for asynchronous account and server actions. +public interface IActionsApi +{ + /// Gets an action by its global action ID. + Task GetAsync(long actionId, CancellationToken cancellationToken = default); + + /// Lists global actions. + Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default); + + /// Streams all global actions. + IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default); + + /// Supplies a requested user interaction for an action. + Task ProceedAsync(long actionId, ProceedRequest request, CancellationToken cancellationToken = default); + + /// Polls an action until BinaryLane reports a terminal state. + Task WaitForCompletionAsync( + long actionId, + ActionWaitOptions? options = null, + CancellationToken cancellationToken = default); +} + +/// +public sealed class ActionsApi : BinaryLaneResourceBase, IActionsApi +{ + private const string FailedStatus = "failed"; + private const string CancelledStatus = "cancelled"; + private const string CanceledStatus = "canceled"; + + /// Initializes the actions resource. + public ActionsApi(IBinaryLaneApiExecutor executor, BinaryLaneJsonSerializerOptions json) + : base(executor, json) + { + } + + /// + public Task GetAsync(long actionId, CancellationToken cancellationToken = default) => + GetItemAsync($"v2/actions/{actionId}", "action", cancellationToken); + + /// + public Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => + GetPageAsync("v2/actions", "actions", page, null, cancellationToken); + + /// + public IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => + GetAllPagesAsync("v2/actions", "actions", page, null, cancellationToken); + + /// + public Task ProceedAsync(long actionId, ProceedRequest request, CancellationToken cancellationToken = default) => + SendNoContentAsync(HttpMethod.Post, $"v2/actions/{actionId}/proceed", request ?? throw new ArgumentNullException(nameof(request)), null, cancellationToken); + + /// + public async Task WaitForCompletionAsync( + long actionId, + ActionWaitOptions? options = null, + CancellationToken cancellationToken = default) + { + options ??= new ActionWaitOptions(); + options.Validate(); + var startedAt = DateTimeOffset.UtcNow; + + while (true) + { + cancellationToken.ThrowIfCancellationRequested(); + var action = await GetAsync(actionId, cancellationToken).ConfigureAwait(false); + if (IsTerminal(action.Status)) + { + return action; + } + + if (DateTimeOffset.UtcNow - startedAt >= options.Timeout) + { + throw new TimeoutException( + $"Timed out waiting for BinaryLane action {actionId} after {options.Timeout}."); + } + + await Task.Delay(options.PollInterval, cancellationToken).ConfigureAwait(false); + } + } + + private static bool IsTerminal(string status) => + string.Equals(status, BinaryLaneValues.ActionStatus.Completed, StringComparison.OrdinalIgnoreCase) || + string.Equals(status, BinaryLaneValues.ActionStatus.Errored, StringComparison.OrdinalIgnoreCase) || + string.Equals(status, FailedStatus, StringComparison.OrdinalIgnoreCase) || + string.Equals(status, CancelledStatus, StringComparison.OrdinalIgnoreCase) || + string.Equals(status, CanceledStatus, StringComparison.OrdinalIgnoreCase); +} diff --git a/src/BinaryLane.Api/Resources/BillingApi.cs b/src/BinaryLane.Api/Resources/BillingApi.cs new file mode 100644 index 0000000..3569afa --- /dev/null +++ b/src/BinaryLane.Api/Resources/BillingApi.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using BinaryLane.Api.V2.Http; +using BinaryLane.Api.V2.Models; +using BinaryLane.Api.V2.Pagination; + +namespace BinaryLane.Api.V2.Resources; + +/// Reads account billing and invoice information. +public interface IBillingApi +{ + Task GetBalanceAsync(CancellationToken cancellationToken = default); + Task GetInvoiceAsync(long invoiceId, CancellationToken cancellationToken = default); + Task> ListInvoicesAsync(PageRequest? page = null, CancellationToken cancellationToken = default); + Task> ListUnpaidPaymentFailedInvoicesAsync(CancellationToken cancellationToken = default); +} + +/// +public sealed class BillingApi : BinaryLaneResourceBase, IBillingApi +{ + /// Initializes the billing resource. + public BillingApi(IBinaryLaneApiExecutor executor, BinaryLaneJsonSerializerOptions json) + : base(executor, json) + { + } + + /// + public Task GetBalanceAsync(CancellationToken cancellationToken = default) => + GetItemAsync("v2/customers/my/balance", "balance", cancellationToken); + + /// + public Task GetInvoiceAsync(long invoiceId, CancellationToken cancellationToken = default) => + GetItemAsync($"v2/customers/my/invoices/{invoiceId}", "invoice", cancellationToken); + + /// + public Task> ListInvoicesAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => + GetPageAsync("v2/customers/my/invoices", "invoices", page, null, cancellationToken); + + /// + public Task> ListUnpaidPaymentFailedInvoicesAsync(CancellationToken cancellationToken = default) => + GetItemAsync>("v2/customers/my/unpaid-payment-failed-invoices", "invoices", cancellationToken); +} diff --git a/src/BinaryLane.Api/Resources/DataUsageApi.cs b/src/BinaryLane.Api/Resources/DataUsageApi.cs new file mode 100644 index 0000000..1aa92c7 --- /dev/null +++ b/src/BinaryLane.Api/Resources/DataUsageApi.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using BinaryLane.Api.V2.Http; +using BinaryLane.Api.V2.Models; +using BinaryLane.Api.V2.Pagination; + +namespace BinaryLane.Api.V2.Resources; + +/// Reads data-transfer usage data. +public interface IDataUsageApi +{ + Task> ListCurrentAsync(PageRequest? page = null, CancellationToken cancellationToken = default); + IAsyncEnumerable ListAllCurrentAsync(PageRequest? page = null, CancellationToken cancellationToken = default); + Task GetCurrentAsync(long serverId, CancellationToken cancellationToken = default); +} + +/// +public sealed class DataUsageApi : BinaryLaneResourceBase, IDataUsageApi +{ + /// Initializes the data-usage resource. + public DataUsageApi(IBinaryLaneApiExecutor executor, BinaryLaneJsonSerializerOptions json) + : base(executor, json) + { + } + + /// + public Task> ListCurrentAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => + GetPageAsync("v2/data_usages/current", "data_usages", page, null, cancellationToken); + + /// + public IAsyncEnumerable ListAllCurrentAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => + GetAllPagesAsync("v2/data_usages/current", "data_usages", page, null, cancellationToken); + + /// + public Task GetCurrentAsync(long serverId, CancellationToken cancellationToken = default) => + GetItemAsync($"v2/data_usages/{serverId}/current", "data_usage", cancellationToken); +} diff --git a/src/BinaryLane.Api/Resources/DomainsApi.cs b/src/BinaryLane.Api/Resources/DomainsApi.cs new file mode 100644 index 0000000..0b8bc78 --- /dev/null +++ b/src/BinaryLane.Api/Resources/DomainsApi.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using BinaryLane.Api.V2.Http; +using BinaryLane.Api.V2.Models; +using BinaryLane.Api.V2.Pagination; + +namespace BinaryLane.Api.V2.Resources; + +/// Manages DNS domains and DNS records. +public interface IDomainsApi +{ + Task> GetNameserversAsync(CancellationToken cancellationToken = default); + Task RefreshNameserverCacheAsync(DomainRefreshRequest request, CancellationToken cancellationToken = default); + Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default); + IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default); + Task CreateAsync(DomainRequest request, CancellationToken cancellationToken = default); + Task GetAsync(string domainName, CancellationToken cancellationToken = default); + Task DeleteAsync(string domainName, CancellationToken cancellationToken = default); + Task> ListRecordsAsync(string domainName, PageRequest? page = null, CancellationToken cancellationToken = default); + Task CreateRecordAsync(string domainName, DomainRecordRequest request, CancellationToken cancellationToken = default); + Task GetRecordAsync(string domainName, long recordId, CancellationToken cancellationToken = default); + Task UpdateRecordAsync(string domainName, long recordId, UpdateDomainRecordRequest request, CancellationToken cancellationToken = default); + Task DeleteRecordAsync(string domainName, long recordId, CancellationToken cancellationToken = default); +} + +/// +public sealed class DomainsApi : BinaryLaneResourceBase, IDomainsApi +{ + /// Initializes the domains resource. + public DomainsApi(IBinaryLaneApiExecutor executor, BinaryLaneJsonSerializerOptions json) + : base(executor, json) + { + } + + /// + public Task> GetNameserversAsync(CancellationToken cancellationToken = default) => + GetItemAsync>("v2/domains/nameservers", "local_nameservers", cancellationToken); + + /// + public Task RefreshNameserverCacheAsync(DomainRefreshRequest request, CancellationToken cancellationToken = default) => + SendNoContentAsync(HttpMethod.Post, "v2/domains/refresh_nameserver_cache", request ?? throw new ArgumentNullException(nameof(request)), null, cancellationToken); + + /// + public Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => + GetPageAsync("v2/domains", "domains", page, null, cancellationToken); + + /// + public IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => + GetAllPagesAsync("v2/domains", "domains", page, null, cancellationToken); + + /// + public Task CreateAsync(DomainRequest request, CancellationToken cancellationToken = default) => + SendItemAsync(HttpMethod.Post, "v2/domains", request ?? throw new ArgumentNullException(nameof(request)), "domain", cancellationToken); + + /// + public Task GetAsync(string domainName, CancellationToken cancellationToken = default) => + GetItemAsync($"v2/domains/{EscapePathSegment(domainName)}", "domain", cancellationToken); + + /// + public Task DeleteAsync(string domainName, CancellationToken cancellationToken = default) => + Executor.DeleteAsync($"v2/domains/{EscapePathSegment(domainName)}", null, null, cancellationToken); + + /// + public Task> ListRecordsAsync(string domainName, PageRequest? page = null, CancellationToken cancellationToken = default) => + GetPageAsync($"v2/domains/{EscapePathSegment(domainName)}/records", "domain_records", page, null, cancellationToken); + + /// + public Task CreateRecordAsync(string domainName, DomainRecordRequest request, CancellationToken cancellationToken = default) => + SendItemAsync(HttpMethod.Post, $"v2/domains/{EscapePathSegment(domainName)}/records", request ?? throw new ArgumentNullException(nameof(request)), "domain_record", cancellationToken); + + /// + public Task GetRecordAsync(string domainName, long recordId, CancellationToken cancellationToken = default) => + GetItemAsync($"v2/domains/{EscapePathSegment(domainName)}/records/{recordId}", "domain_record", cancellationToken); + + /// + public Task UpdateRecordAsync(string domainName, long recordId, UpdateDomainRecordRequest request, CancellationToken cancellationToken = default) => + SendItemAsync(HttpMethod.Put, $"v2/domains/{EscapePathSegment(domainName)}/records/{recordId}", request ?? throw new ArgumentNullException(nameof(request)), "domain_record", cancellationToken); + + /// + public Task DeleteRecordAsync(string domainName, long recordId, CancellationToken cancellationToken = default) => + Executor.DeleteAsync($"v2/domains/{EscapePathSegment(domainName)}/records/{recordId}", null, null, cancellationToken); + +} diff --git a/src/BinaryLane.Api/Resources/ImagesApi.cs b/src/BinaryLane.Api/Resources/ImagesApi.cs new file mode 100644 index 0000000..c0e1872 --- /dev/null +++ b/src/BinaryLane.Api/Resources/ImagesApi.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using BinaryLane.Api.V2.Http; +using BinaryLane.Api.V2.Models; +using BinaryLane.Api.V2.Pagination; + +namespace BinaryLane.Api.V2.Resources; + +/// Reads and manages account images and backups represented as images. +public interface IImagesApi +{ + Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default); + IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default); + Task GetAsync(string imageIdOrSlug, CancellationToken cancellationToken = default); + Task UpdateAsync(long imageId, ImageRequest request, CancellationToken cancellationToken = default); + Task GetDownloadAsync(long imageId, CancellationToken cancellationToken = default); +} + +/// +public sealed class ImagesApi : BinaryLaneResourceBase, IImagesApi +{ + /// Initializes the images resource. + public ImagesApi(IBinaryLaneApiExecutor executor, BinaryLaneJsonSerializerOptions json) + : base(executor, json) + { + } + + /// + public Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => + GetPageAsync("v2/images", "images", page, null, cancellationToken); + + /// + public IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => + GetAllPagesAsync("v2/images", "images", page, null, cancellationToken); + + /// + public Task GetAsync(string imageIdOrSlug, CancellationToken cancellationToken = default) => + GetItemAsync($"v2/images/{EscapePathSegment(imageIdOrSlug)}", "image", cancellationToken); + + /// + public Task UpdateAsync(long imageId, ImageRequest request, CancellationToken cancellationToken = default) => + SendItemAsync(HttpMethod.Put, $"v2/images/{imageId}", request ?? throw new ArgumentNullException(nameof(request)), "image", cancellationToken); + + /// + public Task GetDownloadAsync(long imageId, CancellationToken cancellationToken = default) => + GetItemAsync($"v2/images/{imageId}/download", "link", cancellationToken); +} diff --git a/src/BinaryLane.Api/Resources/LoadBalancersApi.cs b/src/BinaryLane.Api/Resources/LoadBalancersApi.cs new file mode 100644 index 0000000..2087a08 --- /dev/null +++ b/src/BinaryLane.Api/Resources/LoadBalancersApi.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using BinaryLane.Api.V2.Http; +using BinaryLane.Api.V2.Models; +using BinaryLane.Api.V2.Pagination; + +namespace BinaryLane.Api.V2.Resources; + +/// Manages load balancers, their members, and forwarding rules. +public interface ILoadBalancersApi +{ + Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default); + IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default); + Task GetAsync(long loadBalancerId, CancellationToken cancellationToken = default); + Task CreateAsync(CreateLoadBalancerRequest request, CancellationToken cancellationToken = default); + Task UpdateAsync(long loadBalancerId, UpdateLoadBalancerRequest request, CancellationToken cancellationToken = default); + Task DeleteAsync(long loadBalancerId, CancellationToken cancellationToken = default); + Task> GetAvailabilityAsync(CancellationToken cancellationToken = default); + Task AddServersAsync(long loadBalancerId, ServerIdsRequest request, CancellationToken cancellationToken = default); + Task RemoveServersAsync(long loadBalancerId, ServerIdsRequest request, CancellationToken cancellationToken = default); + Task AddForwardingRulesAsync(long loadBalancerId, ForwardingRulesRequest request, CancellationToken cancellationToken = default); + Task RemoveForwardingRulesAsync(long loadBalancerId, ForwardingRulesRequest request, CancellationToken cancellationToken = default); +} + +/// +public sealed class LoadBalancersApi : BinaryLaneResourceBase, ILoadBalancersApi +{ + /// Initializes the load-balancer resource. + public LoadBalancersApi(IBinaryLaneApiExecutor executor, BinaryLaneJsonSerializerOptions json) + : base(executor, json) + { + } + + /// + public Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => + GetPageAsync("v2/load_balancers", "load_balancers", page, null, cancellationToken); + + /// + public IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => + GetAllPagesAsync("v2/load_balancers", "load_balancers", page, null, cancellationToken); + + /// + public Task GetAsync(long loadBalancerId, CancellationToken cancellationToken = default) => + GetItemAsync($"v2/load_balancers/{loadBalancerId}", "load_balancer", cancellationToken); + + /// + public Task CreateAsync(CreateLoadBalancerRequest request, CancellationToken cancellationToken = default) => + SendItemAsync(HttpMethod.Post, "v2/load_balancers", request ?? throw new ArgumentNullException(nameof(request)), "load_balancer", cancellationToken); + + /// + public Task UpdateAsync(long loadBalancerId, UpdateLoadBalancerRequest request, CancellationToken cancellationToken = default) => + SendItemAsync(HttpMethod.Put, $"v2/load_balancers/{loadBalancerId}", request ?? throw new ArgumentNullException(nameof(request)), "load_balancer", cancellationToken); + + /// + public Task DeleteAsync(long loadBalancerId, CancellationToken cancellationToken = default) => + Executor.DeleteAsync($"v2/load_balancers/{loadBalancerId}", null, null, cancellationToken); + + /// + public Task> GetAvailabilityAsync(CancellationToken cancellationToken = default) => + GetItemAsync>( + "v2/load_balancers/availability", + "load_balancer_availability_options", + cancellationToken); + + /// + public Task AddServersAsync(long loadBalancerId, ServerIdsRequest request, CancellationToken cancellationToken = default) => + SendNoContentAsync(HttpMethod.Post, $"v2/load_balancers/{loadBalancerId}/servers", request ?? throw new ArgumentNullException(nameof(request)), null, cancellationToken); + + /// + public Task RemoveServersAsync(long loadBalancerId, ServerIdsRequest request, CancellationToken cancellationToken = default) => + Executor.DeleteAsync($"v2/load_balancers/{loadBalancerId}/servers", request ?? throw new ArgumentNullException(nameof(request)), null, cancellationToken); + + /// + public Task AddForwardingRulesAsync(long loadBalancerId, ForwardingRulesRequest request, CancellationToken cancellationToken = default) => + SendNoContentAsync(HttpMethod.Post, $"v2/load_balancers/{loadBalancerId}/forwarding_rules", request ?? throw new ArgumentNullException(nameof(request)), null, cancellationToken); + + /// + public Task RemoveForwardingRulesAsync(long loadBalancerId, ForwardingRulesRequest request, CancellationToken cancellationToken = default) => + Executor.DeleteAsync($"v2/load_balancers/{loadBalancerId}/forwarding_rules", request ?? throw new ArgumentNullException(nameof(request)), null, cancellationToken); +} diff --git a/src/BinaryLane.Api/Resources/RegionsApi.cs b/src/BinaryLane.Api/Resources/RegionsApi.cs new file mode 100644 index 0000000..5a41b96 --- /dev/null +++ b/src/BinaryLane.Api/Resources/RegionsApi.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using BinaryLane.Api.V2.Http; +using BinaryLane.Api.V2.Models; +using BinaryLane.Api.V2.Pagination; + +namespace BinaryLane.Api.V2.Resources; + +/// Lists BinaryLane regions. +public interface IRegionsApi +{ + Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default); + IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default); +} + +/// +public sealed class RegionsApi : BinaryLaneResourceBase, IRegionsApi +{ + /// Initializes the regions resource. + public RegionsApi(IBinaryLaneApiExecutor executor, BinaryLaneJsonSerializerOptions json) + : base(executor, json) + { + } + + /// + public Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => + GetPageAsync("v2/regions", "regions", page, null, cancellationToken); + + /// + public IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => + GetAllPagesAsync("v2/regions", "regions", page, null, cancellationToken); +} + +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using BinaryLane.Api.V2.Http; +using BinaryLane.Api.V2.Models; +using BinaryLane.Api.V2.Pagination; + +namespace BinaryLane.Api.V2.Resources; diff --git a/src/BinaryLane.Api/Resources/ResourceClients.Part1.cs b/src/BinaryLane.Api/Resources/ResourceClients.Part1.cs deleted file mode 100644 index f7809e0..0000000 --- a/src/BinaryLane.Api/Resources/ResourceClients.Part1.cs +++ /dev/null @@ -1,337 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Net.Http; -using System.Text.Json; -using System.Threading; -using System.Threading.Tasks; -using BinaryLane.Api.V2.Http; -using BinaryLane.Api.V2.Models; -using BinaryLane.Api.V2.Pagination; - -namespace BinaryLane.Api.V2.Resources; - -/// -public sealed class AccountApi : BinaryLaneResourceBase, IAccountApi -{ - /// Initializes the account resource. - public AccountApi(IBinaryLaneApiExecutor executor, BinaryLaneJsonSerializerOptions json) - : base(executor, json) - { - } - - /// - public Task GetAsync(CancellationToken cancellationToken = default) => - GetItemAsync("v2/account", "account", cancellationToken); - - /// - public Task GetRawAsync(CancellationToken cancellationToken = default) => - base.GetRawAsync("v2/account", null, cancellationToken); -} - -/// -public sealed class ActionsApi : BinaryLaneResourceBase, IActionsApi -{ - /// Initializes the actions resource. - public ActionsApi(IBinaryLaneApiExecutor executor, BinaryLaneJsonSerializerOptions json) - : base(executor, json) - { - } - - /// - public Task GetAsync(long actionId, CancellationToken cancellationToken = default) => - GetItemAsync($"v2/actions/{actionId}", "action", cancellationToken); - - /// - public Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => - GetPageAsync("v2/actions", "actions", page, null, cancellationToken); - - /// - public IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => - GetAllPagesAsync("v2/actions", "actions", page, null, cancellationToken); - - /// - public Task ProceedAsync(long actionId, ProceedRequest request, CancellationToken cancellationToken = default) => - SendNoContentAsync(HttpMethod.Post, $"v2/actions/{actionId}/proceed", request ?? throw new ArgumentNullException(nameof(request)), null, cancellationToken); - - /// - public async Task WaitForCompletionAsync( - long actionId, - ActionWaitOptions? options = null, - CancellationToken cancellationToken = default) - { - options ??= new ActionWaitOptions(); - options.Validate(); - var startedAt = DateTimeOffset.UtcNow; - - while (true) - { - cancellationToken.ThrowIfCancellationRequested(); - var action = await GetAsync(actionId, cancellationToken).ConfigureAwait(false); - if (IsTerminal(action.Status)) - { - return action; - } - - if (DateTimeOffset.UtcNow - startedAt >= options.Timeout) - { - throw new TimeoutException( - $"Timed out waiting for BinaryLane action {actionId} after {options.Timeout}."); - } - - await Task.Delay(options.PollInterval, cancellationToken).ConfigureAwait(false); - } - } - - private static bool IsTerminal(string status) => - string.Equals(status, "completed", StringComparison.OrdinalIgnoreCase) || - string.Equals(status, "errored", StringComparison.OrdinalIgnoreCase) || - string.Equals(status, "failed", StringComparison.OrdinalIgnoreCase) || - string.Equals(status, "cancelled", StringComparison.OrdinalIgnoreCase) || - string.Equals(status, "canceled", StringComparison.OrdinalIgnoreCase); -} - -/// -public sealed class BillingApi : BinaryLaneResourceBase, IBillingApi -{ - /// Initializes the billing resource. - public BillingApi(IBinaryLaneApiExecutor executor, BinaryLaneJsonSerializerOptions json) - : base(executor, json) - { - } - - /// - public Task GetBalanceAsync(CancellationToken cancellationToken = default) => - GetItemAsync("v2/customers/my/balance", "balance", cancellationToken); - - /// - public Task GetInvoiceAsync(long invoiceId, CancellationToken cancellationToken = default) => - GetItemAsync($"v2/customers/my/invoices/{invoiceId}", "invoice", cancellationToken); - - /// - public Task> ListInvoicesAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => - GetPageAsync("v2/customers/my/invoices", "invoices", page, null, cancellationToken); - - /// - public Task> ListUnpaidPaymentFailedInvoicesAsync(CancellationToken cancellationToken = default) => - GetItemAsync>("v2/customers/my/unpaid-payment-failed-invoices", "invoices", cancellationToken); -} - -/// -public sealed class DataUsageApi : BinaryLaneResourceBase, IDataUsageApi -{ - /// Initializes the data-usage resource. - public DataUsageApi(IBinaryLaneApiExecutor executor, BinaryLaneJsonSerializerOptions json) - : base(executor, json) - { - } - - /// - public Task> ListCurrentAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => - GetPageAsync("v2/data_usages/current", "data_usages", page, null, cancellationToken); - - /// - public IAsyncEnumerable ListAllCurrentAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => - GetAllPagesAsync("v2/data_usages/current", "data_usages", page, null, cancellationToken); - - /// - public Task GetCurrentAsync(long serverId, CancellationToken cancellationToken = default) => - GetItemAsync($"v2/data_usages/{serverId}/current", "data_usage", cancellationToken); -} - -/// -public sealed class DomainsApi : BinaryLaneResourceBase, IDomainsApi -{ - /// Initializes the domains resource. - public DomainsApi(IBinaryLaneApiExecutor executor, BinaryLaneJsonSerializerOptions json) - : base(executor, json) - { - } - - /// - public Task> GetNameserversAsync(CancellationToken cancellationToken = default) => - GetItemAsync>("v2/domains/nameservers", "local_nameservers", cancellationToken); - - /// - public Task RefreshNameserverCacheAsync(DomainRefreshRequest request, CancellationToken cancellationToken = default) => - SendNoContentAsync(HttpMethod.Post, "v2/domains/refresh_nameserver_cache", request ?? throw new ArgumentNullException(nameof(request)), null, cancellationToken); - - /// - public Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => - GetPageAsync("v2/domains", "domains", page, null, cancellationToken); - - /// - public IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => - GetAllPagesAsync("v2/domains", "domains", page, null, cancellationToken); - - /// - public Task CreateAsync(DomainRequest request, CancellationToken cancellationToken = default) => - SendItemAsync(HttpMethod.Post, "v2/domains", request ?? throw new ArgumentNullException(nameof(request)), "domain", cancellationToken); - - /// - public Task GetAsync(string domainName, CancellationToken cancellationToken = default) => - GetItemAsync($"v2/domains/{EscapePathSegment(domainName)}", "domain", cancellationToken); - - /// - public Task DeleteAsync(string domainName, CancellationToken cancellationToken = default) => - Executor.DeleteAsync($"v2/domains/{EscapePathSegment(domainName)}", null, null, cancellationToken); - - /// - public Task> ListRecordsAsync(string domainName, PageRequest? page = null, CancellationToken cancellationToken = default) => - GetPageAsync($"v2/domains/{EscapePathSegment(domainName)}/records", "domain_records", page, null, cancellationToken); - - /// - public Task CreateRecordAsync(string domainName, DomainRecordRequest request, CancellationToken cancellationToken = default) => - SendItemAsync(HttpMethod.Post, $"v2/domains/{EscapePathSegment(domainName)}/records", request ?? throw new ArgumentNullException(nameof(request)), "domain_record", cancellationToken); - - /// - public Task GetRecordAsync(string domainName, long recordId, CancellationToken cancellationToken = default) => - GetItemAsync($"v2/domains/{EscapePathSegment(domainName)}/records/{recordId}", "domain_record", cancellationToken); - - /// - public Task UpdateRecordAsync(string domainName, long recordId, UpdateDomainRecordRequest request, CancellationToken cancellationToken = default) => - SendItemAsync(HttpMethod.Put, $"v2/domains/{EscapePathSegment(domainName)}/records/{recordId}", request ?? throw new ArgumentNullException(nameof(request)), "domain_record", cancellationToken); - - /// - public Task DeleteRecordAsync(string domainName, long recordId, CancellationToken cancellationToken = default) => - Executor.DeleteAsync($"v2/domains/{EscapePathSegment(domainName)}/records/{recordId}", null, null, cancellationToken); - -} - -/// -public sealed class ImagesApi : BinaryLaneResourceBase, IImagesApi -{ - /// Initializes the images resource. - public ImagesApi(IBinaryLaneApiExecutor executor, BinaryLaneJsonSerializerOptions json) - : base(executor, json) - { - } - - /// - public Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => - GetPageAsync("v2/images", "images", page, null, cancellationToken); - - /// - public IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => - GetAllPagesAsync("v2/images", "images", page, null, cancellationToken); - - /// - public Task GetAsync(string imageIdOrSlug, CancellationToken cancellationToken = default) => - GetItemAsync($"v2/images/{EscapePathSegment(imageIdOrSlug)}", "image", cancellationToken); - - /// - public Task UpdateAsync(long imageId, ImageRequest request, CancellationToken cancellationToken = default) => - SendItemAsync(HttpMethod.Put, $"v2/images/{imageId}", request ?? throw new ArgumentNullException(nameof(request)), "image", cancellationToken); - - /// - public Task GetDownloadAsync(long imageId, CancellationToken cancellationToken = default) => - GetItemAsync($"v2/images/{imageId}/download", "link", cancellationToken); -} - -/// -public sealed class SshKeysApi : BinaryLaneResourceBase, ISshKeysApi -{ - /// Initializes the SSH-key resource. - public SshKeysApi(IBinaryLaneApiExecutor executor, BinaryLaneJsonSerializerOptions json) - : base(executor, json) - { - } - - /// - public Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => - GetPageAsync("v2/account/keys", "ssh_keys", page, null, cancellationToken); - - /// - public IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => - GetAllPagesAsync("v2/account/keys", "ssh_keys", page, null, cancellationToken); - - /// - public Task GetAsync(long keyId, CancellationToken cancellationToken = default) => - GetItemAsync($"v2/account/keys/{keyId}", "ssh_key", cancellationToken); - - /// - public Task CreateAsync(SshKeyRequest request, CancellationToken cancellationToken = default) => - SendItemAsync(HttpMethod.Post, "v2/account/keys", request ?? throw new ArgumentNullException(nameof(request)), "ssh_key", cancellationToken); - - /// - public Task UpdateAsync(long keyId, UpdateSshKeyRequest request, CancellationToken cancellationToken = default) => - SendItemAsync(HttpMethod.Put, $"v2/account/keys/{keyId}", request ?? throw new ArgumentNullException(nameof(request)), "ssh_key", cancellationToken); - - /// - public Task DeleteAsync(long keyId, CancellationToken cancellationToken = default) => - Executor.DeleteAsync($"v2/account/keys/{keyId}", null, null, cancellationToken); -} - -/// -public sealed class LoadBalancersApi : BinaryLaneResourceBase, ILoadBalancersApi -{ - /// Initializes the load-balancer resource. - public LoadBalancersApi(IBinaryLaneApiExecutor executor, BinaryLaneJsonSerializerOptions json) - : base(executor, json) - { - } - - /// - public Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => - GetPageAsync("v2/load_balancers", "load_balancers", page, null, cancellationToken); - - /// - public IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => - GetAllPagesAsync("v2/load_balancers", "load_balancers", page, null, cancellationToken); - - /// - public Task GetAsync(long loadBalancerId, CancellationToken cancellationToken = default) => - GetItemAsync($"v2/load_balancers/{loadBalancerId}", "load_balancer", cancellationToken); - - /// - public Task CreateAsync(CreateLoadBalancerRequest request, CancellationToken cancellationToken = default) => - SendItemAsync(HttpMethod.Post, "v2/load_balancers", request ?? throw new ArgumentNullException(nameof(request)), "load_balancer", cancellationToken); - - /// - public Task UpdateAsync(long loadBalancerId, UpdateLoadBalancerRequest request, CancellationToken cancellationToken = default) => - SendItemAsync(HttpMethod.Put, $"v2/load_balancers/{loadBalancerId}", request ?? throw new ArgumentNullException(nameof(request)), "load_balancer", cancellationToken); - - /// - public Task DeleteAsync(long loadBalancerId, CancellationToken cancellationToken = default) => - Executor.DeleteAsync($"v2/load_balancers/{loadBalancerId}", null, null, cancellationToken); - - /// - public Task> GetAvailabilityAsync(CancellationToken cancellationToken = default) => - GetItemAsync>( - "v2/load_balancers/availability", - "load_balancer_availability_options", - cancellationToken); - - /// - public Task AddServersAsync(long loadBalancerId, ServerIdsRequest request, CancellationToken cancellationToken = default) => - SendNoContentAsync(HttpMethod.Post, $"v2/load_balancers/{loadBalancerId}/servers", request ?? throw new ArgumentNullException(nameof(request)), null, cancellationToken); - - /// - public Task RemoveServersAsync(long loadBalancerId, ServerIdsRequest request, CancellationToken cancellationToken = default) => - Executor.DeleteAsync($"v2/load_balancers/{loadBalancerId}/servers", request ?? throw new ArgumentNullException(nameof(request)), null, cancellationToken); - - /// - public Task AddForwardingRulesAsync(long loadBalancerId, ForwardingRulesRequest request, CancellationToken cancellationToken = default) => - SendNoContentAsync(HttpMethod.Post, $"v2/load_balancers/{loadBalancerId}/forwarding_rules", request ?? throw new ArgumentNullException(nameof(request)), null, cancellationToken); - - /// - public Task RemoveForwardingRulesAsync(long loadBalancerId, ForwardingRulesRequest request, CancellationToken cancellationToken = default) => - Executor.DeleteAsync($"v2/load_balancers/{loadBalancerId}/forwarding_rules", request ?? throw new ArgumentNullException(nameof(request)), null, cancellationToken); -} - -/// -public sealed class RegionsApi : BinaryLaneResourceBase, IRegionsApi -{ - /// Initializes the regions resource. - public RegionsApi(IBinaryLaneApiExecutor executor, BinaryLaneJsonSerializerOptions json) - : base(executor, json) - { - } - - /// - public Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => - GetPageAsync("v2/regions", "regions", page, null, cancellationToken); - - /// - public IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => - GetAllPagesAsync("v2/regions", "regions", page, null, cancellationToken); -} diff --git a/src/BinaryLane.Api/Resources/ResourceClients.Part2.cs b/src/BinaryLane.Api/Resources/ResourceClients.Part2.cs deleted file mode 100644 index d2e8c46..0000000 --- a/src/BinaryLane.Api/Resources/ResourceClients.Part2.cs +++ /dev/null @@ -1,286 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Net.Http; -using System.Text.Json; -using System.Threading; -using System.Threading.Tasks; -using BinaryLane.Api.V2.Http; -using BinaryLane.Api.V2.Models; -using BinaryLane.Api.V2.Pagination; - -namespace BinaryLane.Api.V2.Resources; - -/// -public sealed class ReverseNamesApi : BinaryLaneResourceBase, IReverseNamesApi -{ - /// Initializes the reverse-names resource. - public ReverseNamesApi(IBinaryLaneApiExecutor executor, BinaryLaneJsonSerializerOptions json) - : base(executor, json) - { - } - - /// - public Task> ListIpv6Async(PageRequest? page = null, CancellationToken cancellationToken = default) => - GetPageAsync("v2/reverse_names/ipv6", "reverse_nameservers", page, null, cancellationToken); - - /// - public IAsyncEnumerable ListAllIpv6Async(PageRequest? page = null, CancellationToken cancellationToken = default) => - GetAllPagesAsync("v2/reverse_names/ipv6", "reverse_nameservers", page, null, cancellationToken); - - /// - public async Task UpdateIpv6Async(ReverseNameserversRequest request, CancellationToken cancellationToken = default) - { - var response = await SendResponseAsync( - HttpMethod.Post, - "v2/reverse_names/ipv6", - request ?? throw new ArgumentNullException(nameof(request)), - null, - cancellationToken).ConfigureAwait(false); - TryDeserializeEnvelope(response.Body, "action", out var action); - return new ActionSubmission(response.StatusCode, action, response.Body); - } -} - -/// -public sealed class SampleSetsApi : BinaryLaneResourceBase, ISampleSetsApi -{ - /// Initializes the monitoring sample-set resource. - public SampleSetsApi(IBinaryLaneApiExecutor executor, BinaryLaneJsonSerializerOptions json) - : base(executor, json) - { - } - - /// - public async Task GetLatestAsync(long serverId, string? dataInterval = null, CancellationToken cancellationToken = default) - { - IReadOnlyDictionary? query = string.IsNullOrWhiteSpace(dataInterval) - ? null - : new Dictionary { ["data_interval"] = dataInterval }; - var response = await GetRawAsync($"v2/samplesets/{serverId}/latest", query, cancellationToken).ConfigureAwait(false); - return TryDeserializeEnvelope(response, "sample_set", out var sampleSet) ? sampleSet : null; - } - - /// - public Task> ListAsync( - long serverId, - PageRequest? page = null, - string? dataInterval = null, - DateTimeOffset? start = null, - DateTimeOffset? endAt = null, - CancellationToken cancellationToken = default) - { - var query = new Dictionary - { - ["data_interval"] = dataInterval, - ["start"] = start, - ["end"] = endAt, - }; - return GetPageAsync($"v2/samplesets/{serverId}", "sample_sets", page, query, cancellationToken); - } -} - -/// -public sealed class ServersApi : BinaryLaneResourceBase, IServersApi -{ - /// Initializes the servers resource. - public ServersApi(IBinaryLaneApiExecutor executor, BinaryLaneJsonSerializerOptions json) - : base(executor, json) - { - } - - /// - public Task GetAsync(long serverId, CancellationToken cancellationToken = default) => - GetItemAsync($"v2/servers/{serverId}", "server", cancellationToken); - - /// - public Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => - GetPageAsync("v2/servers", "servers", page, null, cancellationToken); - - /// - public IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => - GetAllPagesAsync("v2/servers", "servers", page, null, cancellationToken); - - /// - public Task CreateAsync(CreateServerRequest request, CancellationToken cancellationToken = default) => - SendItemAsync(HttpMethod.Post, "v2/servers", request ?? throw new ArgumentNullException(nameof(request)), "server", cancellationToken); - - /// - public Task DeleteAsync(long serverId, string? reason = null, CancellationToken cancellationToken = default) => - Executor.DeleteAsync( - $"v2/servers/{serverId}", - null, - string.IsNullOrWhiteSpace(reason) ? null : new Dictionary { ["reason"] = reason }, - cancellationToken); - - /// - public Task> ListActionsAsync(long serverId, PageRequest? page = null, CancellationToken cancellationToken = default) => - GetPageAsync($"v2/servers/{serverId}/actions", "actions", page, null, cancellationToken); - - /// - public Task GetActionAsync(long serverId, long actionId, CancellationToken cancellationToken = default) => - GetItemAsync($"v2/servers/{serverId}/actions/{actionId}", "action", cancellationToken); - - /// - public async Task SubmitActionAsync(long serverId, ServerAction request, CancellationToken cancellationToken = default) - { -#if NET8_0_OR_GREATER - ArgumentNullException.ThrowIfNull(request); -#else - if (request is null) - { - throw new ArgumentNullException(nameof(request)); - } -#endif - - var response = await SendResponseAsync( - HttpMethod.Post, - $"v2/servers/{serverId}/actions", - request, - null, - cancellationToken).ConfigureAwait(false); - - TryDeserializeEnvelope(response.Body, "action", out var action); - return new ActionSubmission(response.StatusCode, action, response.Body); - } - - /// - public Task> GetAdvancedFirewallRulesAsync(long serverId, CancellationToken cancellationToken = default) => - GetItemAsync>( - $"v2/servers/{serverId}/advanced_firewall_rules", - "firewall_rules", - cancellationToken); - - /// - public Task GetAvailableAdvancedFeaturesAsync(long serverId, CancellationToken cancellationToken = default) => - GetItemAsync( - $"v2/servers/{serverId}/available_advanced_features", - "available_advanced_server_features", - cancellationToken); - - /// - public Task> ListBackupsAsync(long serverId, PageRequest? page = null, CancellationToken cancellationToken = default) => - GetPageAsync($"v2/servers/{serverId}/backups", "backups", page, null, cancellationToken); - - /// - public Task CreateBackupAsync(long serverId, UploadImageRequest request, CancellationToken cancellationToken = default) => - SendItemAsync(HttpMethod.Post, $"v2/servers/{serverId}/backups", request ?? throw new ArgumentNullException(nameof(request)), "action", cancellationToken); - - /// - public Task> ListKernelsAsync(long serverId, PageRequest? page = null, CancellationToken cancellationToken = default) => - GetPageAsync($"v2/servers/{serverId}/kernels", "kernels", page, null, cancellationToken); - - /// - public Task> ListSnapshotsAsync(long serverId, PageRequest? page = null, CancellationToken cancellationToken = default) => - GetPageAsync($"v2/servers/{serverId}/snapshots", "snapshots", page, null, cancellationToken); - - /// - public Task> GetThresholdAlertsAsync(long serverId, CancellationToken cancellationToken = default) => - GetItemAsync>($"v2/servers/{serverId}/threshold_alerts", "threshold_alerts", cancellationToken); - - /// - public Task> GetThresholdAlertServerIdsAsync(CancellationToken cancellationToken = default) => - GetItemAsync>("v2/servers/threshold_alerts", "server_ids", cancellationToken); - - /// - public Task> ListSoftwareAsync(long serverId, PageRequest? page = null, CancellationToken cancellationToken = default) => - GetPageAsync($"v2/servers/{serverId}/software", "licensed_software", page, null, cancellationToken); - - /// - public Task GetUserDataAsync(long serverId, CancellationToken cancellationToken = default) => - GetDirectItemAsync($"v2/servers/{serverId}/user_data", cancellationToken); - - /// - public Task GetConsoleAsync(long serverId, CancellationToken cancellationToken = default) => - GetItemAsync($"v2/servers/{serverId}/console", "console", cancellationToken); -} - -/// -public sealed class SizesApi : BinaryLaneResourceBase, ISizesApi -{ - /// Initializes the sizes resource. - public SizesApi(IBinaryLaneApiExecutor executor, BinaryLaneJsonSerializerOptions json) - : base(executor, json) - { - } - - /// - public Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => - GetPageAsync("v2/sizes", "sizes", page, null, cancellationToken); - - /// - public IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => - GetAllPagesAsync("v2/sizes", "sizes", page, null, cancellationToken); -} - -/// -public sealed class SoftwareApi : BinaryLaneResourceBase, ISoftwareApi -{ - /// Initializes the software resource. - public SoftwareApi(IBinaryLaneApiExecutor executor, BinaryLaneJsonSerializerOptions json) - : base(executor, json) - { - } - - /// - public Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => - GetPageAsync("v2/software", "software", page, null, cancellationToken); - - /// - public IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => - GetAllPagesAsync("v2/software", "software", page, null, cancellationToken); - - /// - public Task GetAsync(long softwareId, CancellationToken cancellationToken = default) => - GetItemAsync($"v2/software/{softwareId}", "software", cancellationToken); - - /// - public Task> ListOperatingSystemAsync(string operatingSystemIdOrSlug, PageRequest? page = null, CancellationToken cancellationToken = default) => - GetPageAsync( - $"v2/software/operating_system/{EscapePathSegment(operatingSystemIdOrSlug)}", - "software", - page, - null, - cancellationToken); -} - -/// -public sealed class VpcsApi : BinaryLaneResourceBase, IVpcsApi -{ - /// Initializes the VPC resource. - public VpcsApi(IBinaryLaneApiExecutor executor, BinaryLaneJsonSerializerOptions json) - : base(executor, json) - { - } - - /// - public Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => - GetPageAsync("v2/vpcs", "vpcs", page, null, cancellationToken); - - /// - public IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => - GetAllPagesAsync("v2/vpcs", "vpcs", page, null, cancellationToken); - - /// - public Task GetAsync(long vpcId, CancellationToken cancellationToken = default) => - GetItemAsync($"v2/vpcs/{vpcId}", "vpc", cancellationToken); - - /// - public Task CreateAsync(CreateVpcRequest request, CancellationToken cancellationToken = default) => - SendItemAsync(HttpMethod.Post, "v2/vpcs", request ?? throw new ArgumentNullException(nameof(request)), "vpc", cancellationToken); - - /// - public Task ReplaceAsync(long vpcId, UpdateVpcRequest request, CancellationToken cancellationToken = default) => - SendItemAsync(HttpMethod.Put, $"v2/vpcs/{vpcId}", request ?? throw new ArgumentNullException(nameof(request)), "vpc", cancellationToken); - - /// - public Task UpdateAsync(long vpcId, PatchVpcRequest request, CancellationToken cancellationToken = default) => - SendItemAsync(new HttpMethod("PATCH"), $"v2/vpcs/{vpcId}", request ?? throw new ArgumentNullException(nameof(request)), "vpc", cancellationToken); - - /// - public Task DeleteAsync(long vpcId, CancellationToken cancellationToken = default) => - Executor.DeleteAsync($"v2/vpcs/{vpcId}", null, null, cancellationToken); - - /// - public Task> ListMembersAsync(long vpcId, PageRequest? page = null, CancellationToken cancellationToken = default) => - GetPageAsync($"v2/vpcs/{vpcId}/members", "members", page, null, cancellationToken); -} diff --git a/src/BinaryLane.Api/Resources/ResourceInterfaces.cs b/src/BinaryLane.Api/Resources/ResourceInterfaces.cs deleted file mode 100644 index 254a2e9..0000000 --- a/src/BinaryLane.Api/Resources/ResourceInterfaces.cs +++ /dev/null @@ -1,186 +0,0 @@ -using System.Collections.Generic; -using System.Text.Json; -using System.Threading; -using System.Threading.Tasks; -using BinaryLane.Api.V2.Models; -using BinaryLane.Api.V2.Pagination; - -namespace BinaryLane.Api.V2.Resources; - -/// Reads information about the authenticated account. -public interface IAccountApi -{ - /// Gets the current account. - Task GetAsync(CancellationToken cancellationToken = default); - - /// Gets the untyped account response for forward compatibility. - Task GetRawAsync(CancellationToken cancellationToken = default); -} - -/// Reads and waits for asynchronous account and server actions. -public interface IActionsApi -{ - /// Gets an action by its global action ID. - Task GetAsync(long actionId, CancellationToken cancellationToken = default); - - /// Lists global actions. - Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default); - - /// Streams all global actions. - IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default); - - /// Supplies a requested user interaction for an action. - Task ProceedAsync(long actionId, ProceedRequest request, CancellationToken cancellationToken = default); - - /// Polls an action until BinaryLane reports a terminal state. - Task WaitForCompletionAsync( - long actionId, - ActionWaitOptions? options = null, - CancellationToken cancellationToken = default); -} - -/// Reads account billing and invoice information. -public interface IBillingApi -{ - Task GetBalanceAsync(CancellationToken cancellationToken = default); - Task GetInvoiceAsync(long invoiceId, CancellationToken cancellationToken = default); - Task> ListInvoicesAsync(PageRequest? page = null, CancellationToken cancellationToken = default); - Task> ListUnpaidPaymentFailedInvoicesAsync(CancellationToken cancellationToken = default); -} - -/// Reads data-transfer usage data. -public interface IDataUsageApi -{ - Task> ListCurrentAsync(PageRequest? page = null, CancellationToken cancellationToken = default); - IAsyncEnumerable ListAllCurrentAsync(PageRequest? page = null, CancellationToken cancellationToken = default); - Task GetCurrentAsync(long serverId, CancellationToken cancellationToken = default); -} - -/// Manages DNS domains and DNS records. -public interface IDomainsApi -{ - Task> GetNameserversAsync(CancellationToken cancellationToken = default); - Task RefreshNameserverCacheAsync(DomainRefreshRequest request, CancellationToken cancellationToken = default); - Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default); - IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default); - Task CreateAsync(DomainRequest request, CancellationToken cancellationToken = default); - Task GetAsync(string domainName, CancellationToken cancellationToken = default); - Task DeleteAsync(string domainName, CancellationToken cancellationToken = default); - Task> ListRecordsAsync(string domainName, PageRequest? page = null, CancellationToken cancellationToken = default); - Task CreateRecordAsync(string domainName, DomainRecordRequest request, CancellationToken cancellationToken = default); - Task GetRecordAsync(string domainName, long recordId, CancellationToken cancellationToken = default); - Task UpdateRecordAsync(string domainName, long recordId, UpdateDomainRecordRequest request, CancellationToken cancellationToken = default); - Task DeleteRecordAsync(string domainName, long recordId, CancellationToken cancellationToken = default); -} - -/// Reads and manages account images and backups represented as images. -public interface IImagesApi -{ - Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default); - IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default); - Task GetAsync(string imageIdOrSlug, CancellationToken cancellationToken = default); - Task UpdateAsync(long imageId, ImageRequest request, CancellationToken cancellationToken = default); - Task GetDownloadAsync(long imageId, CancellationToken cancellationToken = default); -} - -/// Manages account SSH keys. -public interface ISshKeysApi -{ - Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default); - IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default); - Task GetAsync(long keyId, CancellationToken cancellationToken = default); - Task CreateAsync(SshKeyRequest request, CancellationToken cancellationToken = default); - Task UpdateAsync(long keyId, UpdateSshKeyRequest request, CancellationToken cancellationToken = default); - Task DeleteAsync(long keyId, CancellationToken cancellationToken = default); -} - -/// Manages load balancers, their members, and forwarding rules. -public interface ILoadBalancersApi -{ - Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default); - IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default); - Task GetAsync(long loadBalancerId, CancellationToken cancellationToken = default); - Task CreateAsync(CreateLoadBalancerRequest request, CancellationToken cancellationToken = default); - Task UpdateAsync(long loadBalancerId, UpdateLoadBalancerRequest request, CancellationToken cancellationToken = default); - Task DeleteAsync(long loadBalancerId, CancellationToken cancellationToken = default); - Task> GetAvailabilityAsync(CancellationToken cancellationToken = default); - Task AddServersAsync(long loadBalancerId, ServerIdsRequest request, CancellationToken cancellationToken = default); - Task RemoveServersAsync(long loadBalancerId, ServerIdsRequest request, CancellationToken cancellationToken = default); - Task AddForwardingRulesAsync(long loadBalancerId, ForwardingRulesRequest request, CancellationToken cancellationToken = default); - Task RemoveForwardingRulesAsync(long loadBalancerId, ForwardingRulesRequest request, CancellationToken cancellationToken = default); -} - -/// Lists BinaryLane regions. -public interface IRegionsApi -{ - Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default); - IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default); -} - -/// Manages IPv6 reverse-name configuration. -public interface IReverseNamesApi -{ - Task> ListIpv6Async(PageRequest? page = null, CancellationToken cancellationToken = default); - IAsyncEnumerable ListAllIpv6Async(PageRequest? page = null, CancellationToken cancellationToken = default); - Task UpdateIpv6Async(ReverseNameserversRequest request, CancellationToken cancellationToken = default); -} - -/// Reads monitoring samples for servers. -public interface ISampleSetsApi -{ - Task GetLatestAsync(long serverId, string? dataInterval = null, CancellationToken cancellationToken = default); - Task> ListAsync(long serverId, PageRequest? page = null, string? dataInterval = null, DateTimeOffset? start = null, DateTimeOffset? endAt = null, CancellationToken cancellationToken = default); -} - -/// Manages BinaryLane servers and their server-scoped resources. -public interface IServersApi -{ - Task GetAsync(long serverId, CancellationToken cancellationToken = default); - Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default); - IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default); - Task CreateAsync(CreateServerRequest request, CancellationToken cancellationToken = default); - Task DeleteAsync(long serverId, string? reason = null, CancellationToken cancellationToken = default); - Task> ListActionsAsync(long serverId, PageRequest? page = null, CancellationToken cancellationToken = default); - Task GetActionAsync(long serverId, long actionId, CancellationToken cancellationToken = default); - Task SubmitActionAsync(long serverId, ServerAction request, CancellationToken cancellationToken = default); - Task> GetAdvancedFirewallRulesAsync(long serverId, CancellationToken cancellationToken = default); - Task GetAvailableAdvancedFeaturesAsync(long serverId, CancellationToken cancellationToken = default); - Task> ListBackupsAsync(long serverId, PageRequest? page = null, CancellationToken cancellationToken = default); - Task CreateBackupAsync(long serverId, UploadImageRequest request, CancellationToken cancellationToken = default); - Task> ListKernelsAsync(long serverId, PageRequest? page = null, CancellationToken cancellationToken = default); - Task> ListSnapshotsAsync(long serverId, PageRequest? page = null, CancellationToken cancellationToken = default); - Task> GetThresholdAlertsAsync(long serverId, CancellationToken cancellationToken = default); - Task> GetThresholdAlertServerIdsAsync(CancellationToken cancellationToken = default); - Task> ListSoftwareAsync(long serverId, PageRequest? page = null, CancellationToken cancellationToken = default); - Task GetUserDataAsync(long serverId, CancellationToken cancellationToken = default); - Task GetConsoleAsync(long serverId, CancellationToken cancellationToken = default); -} - -/// Lists available server sizes. -public interface ISizesApi -{ - Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default); - IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default); -} - -/// Lists available licensed software and operating-system software. -public interface ISoftwareApi -{ - Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default); - IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default); - Task GetAsync(long softwareId, CancellationToken cancellationToken = default); - Task> ListOperatingSystemAsync(string operatingSystemIdOrSlug, PageRequest? page = null, CancellationToken cancellationToken = default); -} - -/// Manages private virtual networks and their members. -public interface IVpcsApi -{ - Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default); - IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default); - Task GetAsync(long vpcId, CancellationToken cancellationToken = default); - Task CreateAsync(CreateVpcRequest request, CancellationToken cancellationToken = default); - Task ReplaceAsync(long vpcId, UpdateVpcRequest request, CancellationToken cancellationToken = default); - Task UpdateAsync(long vpcId, PatchVpcRequest request, CancellationToken cancellationToken = default); - Task DeleteAsync(long vpcId, CancellationToken cancellationToken = default); - Task> ListMembersAsync(long vpcId, PageRequest? page = null, CancellationToken cancellationToken = default); -} diff --git a/src/BinaryLane.Api/Resources/ReverseNamesApi.cs b/src/BinaryLane.Api/Resources/ReverseNamesApi.cs new file mode 100644 index 0000000..d2ff18b --- /dev/null +++ b/src/BinaryLane.Api/Resources/ReverseNamesApi.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using BinaryLane.Api.V2.Http; +using BinaryLane.Api.V2.Models; +using BinaryLane.Api.V2.Pagination; + +namespace BinaryLane.Api.V2.Resources; + +/// Manages IPv6 reverse-name configuration. +public interface IReverseNamesApi +{ + Task> ListIpv6Async(PageRequest? page = null, CancellationToken cancellationToken = default); + IAsyncEnumerable ListAllIpv6Async(PageRequest? page = null, CancellationToken cancellationToken = default); + Task UpdateIpv6Async(ReverseNameserversRequest request, CancellationToken cancellationToken = default); +} + +/// +public sealed class ReverseNamesApi : BinaryLaneResourceBase, IReverseNamesApi +{ + /// Initializes the reverse-names resource. + public ReverseNamesApi(IBinaryLaneApiExecutor executor, BinaryLaneJsonSerializerOptions json) + : base(executor, json) + { + } + + /// + public Task> ListIpv6Async(PageRequest? page = null, CancellationToken cancellationToken = default) => + GetPageAsync("v2/reverse_names/ipv6", "reverse_nameservers", page, null, cancellationToken); + + /// + public IAsyncEnumerable ListAllIpv6Async(PageRequest? page = null, CancellationToken cancellationToken = default) => + GetAllPagesAsync("v2/reverse_names/ipv6", "reverse_nameservers", page, null, cancellationToken); + + /// + public async Task UpdateIpv6Async(ReverseNameserversRequest request, CancellationToken cancellationToken = default) + { + var response = await SendResponseAsync( + HttpMethod.Post, + "v2/reverse_names/ipv6", + request ?? throw new ArgumentNullException(nameof(request)), + null, + cancellationToken).ConfigureAwait(false); + TryDeserializeEnvelope(response.Body, "action", out var action); + return new ActionSubmission(response.StatusCode, action, response.Body); + } +} diff --git a/src/BinaryLane.Api/Resources/SampleSetsApi.cs b/src/BinaryLane.Api/Resources/SampleSetsApi.cs new file mode 100644 index 0000000..73e75d5 --- /dev/null +++ b/src/BinaryLane.Api/Resources/SampleSetsApi.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using BinaryLane.Api.V2.Http; +using BinaryLane.Api.V2.Models; +using BinaryLane.Api.V2.Pagination; + +namespace BinaryLane.Api.V2.Resources; + +/// Reads monitoring samples for servers. +public interface ISampleSetsApi +{ + Task GetLatestAsync(long serverId, string? dataInterval = null, CancellationToken cancellationToken = default); + Task> ListAsync(long serverId, PageRequest? page = null, string? dataInterval = null, DateTimeOffset? start = null, DateTimeOffset? endAt = null, CancellationToken cancellationToken = default); +} + +/// +public sealed class SampleSetsApi : BinaryLaneResourceBase, ISampleSetsApi +{ + /// Initializes the monitoring sample-set resource. + public SampleSetsApi(IBinaryLaneApiExecutor executor, BinaryLaneJsonSerializerOptions json) + : base(executor, json) + { + } + + /// + public async Task GetLatestAsync(long serverId, string? dataInterval = null, CancellationToken cancellationToken = default) + { + IReadOnlyDictionary? query = string.IsNullOrWhiteSpace(dataInterval) + ? null + : new Dictionary { ["data_interval"] = dataInterval }; + var response = await GetRawAsync($"v2/samplesets/{serverId}/latest", query, cancellationToken).ConfigureAwait(false); + return TryDeserializeEnvelope(response, "sample_set", out var sampleSet) ? sampleSet : null; + } + + /// + public Task> ListAsync( + long serverId, + PageRequest? page = null, + string? dataInterval = null, + DateTimeOffset? start = null, + DateTimeOffset? endAt = null, + CancellationToken cancellationToken = default) + { + var query = new Dictionary + { + ["data_interval"] = dataInterval, + ["start"] = start, + ["end"] = endAt, + }; + return GetPageAsync($"v2/samplesets/{serverId}", "sample_sets", page, query, cancellationToken); + } +} diff --git a/src/BinaryLane.Api/Resources/ServersApi.cs b/src/BinaryLane.Api/Resources/ServersApi.cs new file mode 100644 index 0000000..8a7723f --- /dev/null +++ b/src/BinaryLane.Api/Resources/ServersApi.cs @@ -0,0 +1,150 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using BinaryLane.Api.V2.Http; +using BinaryLane.Api.V2.Models; +using BinaryLane.Api.V2.Pagination; + +namespace BinaryLane.Api.V2.Resources; + +/// Manages BinaryLane servers and their server-scoped resources. +public interface IServersApi +{ + Task GetAsync(long serverId, CancellationToken cancellationToken = default); + Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default); + IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default); + Task CreateAsync(CreateServerRequest request, CancellationToken cancellationToken = default); + Task DeleteAsync(long serverId, string? reason = null, CancellationToken cancellationToken = default); + Task> ListActionsAsync(long serverId, PageRequest? page = null, CancellationToken cancellationToken = default); + Task GetActionAsync(long serverId, long actionId, CancellationToken cancellationToken = default); + Task SubmitActionAsync(long serverId, ServerAction request, CancellationToken cancellationToken = default); + Task> GetAdvancedFirewallRulesAsync(long serverId, CancellationToken cancellationToken = default); + Task GetAvailableAdvancedFeaturesAsync(long serverId, CancellationToken cancellationToken = default); + Task> ListBackupsAsync(long serverId, PageRequest? page = null, CancellationToken cancellationToken = default); + Task CreateBackupAsync(long serverId, UploadImageRequest request, CancellationToken cancellationToken = default); + Task> ListKernelsAsync(long serverId, PageRequest? page = null, CancellationToken cancellationToken = default); + Task> ListSnapshotsAsync(long serverId, PageRequest? page = null, CancellationToken cancellationToken = default); + Task> GetThresholdAlertsAsync(long serverId, CancellationToken cancellationToken = default); + Task> GetThresholdAlertServerIdsAsync(CancellationToken cancellationToken = default); + Task> ListSoftwareAsync(long serverId, PageRequest? page = null, CancellationToken cancellationToken = default); + Task GetUserDataAsync(long serverId, CancellationToken cancellationToken = default); + Task GetConsoleAsync(long serverId, CancellationToken cancellationToken = default); +} + +/// +public sealed class ServersApi : BinaryLaneResourceBase, IServersApi +{ + /// Initializes the servers resource. + public ServersApi(IBinaryLaneApiExecutor executor, BinaryLaneJsonSerializerOptions json) + : base(executor, json) + { + } + + /// + public Task GetAsync(long serverId, CancellationToken cancellationToken = default) => + GetItemAsync($"v2/servers/{serverId}", "server", cancellationToken); + + /// + public Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => + GetPageAsync("v2/servers", "servers", page, null, cancellationToken); + + /// + public IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => + GetAllPagesAsync("v2/servers", "servers", page, null, cancellationToken); + + /// + public Task CreateAsync(CreateServerRequest request, CancellationToken cancellationToken = default) => + SendItemAsync(HttpMethod.Post, "v2/servers", request ?? throw new ArgumentNullException(nameof(request)), "server", cancellationToken); + + /// + public Task DeleteAsync(long serverId, string? reason = null, CancellationToken cancellationToken = default) => + Executor.DeleteAsync( + $"v2/servers/{serverId}", + null, + string.IsNullOrWhiteSpace(reason) ? null : new Dictionary { ["reason"] = reason }, + cancellationToken); + + /// + public Task> ListActionsAsync(long serverId, PageRequest? page = null, CancellationToken cancellationToken = default) => + GetPageAsync($"v2/servers/{serverId}/actions", "actions", page, null, cancellationToken); + + /// + public Task GetActionAsync(long serverId, long actionId, CancellationToken cancellationToken = default) => + GetItemAsync($"v2/servers/{serverId}/actions/{actionId}", "action", cancellationToken); + + /// + public async Task SubmitActionAsync(long serverId, ServerAction request, CancellationToken cancellationToken = default) + { +#if NET8_0_OR_GREATER + ArgumentNullException.ThrowIfNull(request); +#else + if (request is null) + { + throw new ArgumentNullException(nameof(request)); + } +#endif + + var response = await SendResponseAsync( + HttpMethod.Post, + $"v2/servers/{serverId}/actions", + request, + null, + cancellationToken).ConfigureAwait(false); + + TryDeserializeEnvelope(response.Body, "action", out var action); + return new ActionSubmission(response.StatusCode, action, response.Body); + } + + /// + public Task> GetAdvancedFirewallRulesAsync(long serverId, CancellationToken cancellationToken = default) => + GetItemAsync>( + $"v2/servers/{serverId}/advanced_firewall_rules", + "firewall_rules", + cancellationToken); + + /// + public Task GetAvailableAdvancedFeaturesAsync(long serverId, CancellationToken cancellationToken = default) => + GetItemAsync( + $"v2/servers/{serverId}/available_advanced_features", + "available_advanced_server_features", + cancellationToken); + + /// + public Task> ListBackupsAsync(long serverId, PageRequest? page = null, CancellationToken cancellationToken = default) => + GetPageAsync($"v2/servers/{serverId}/backups", "backups", page, null, cancellationToken); + + /// + public Task CreateBackupAsync(long serverId, UploadImageRequest request, CancellationToken cancellationToken = default) => + SendItemAsync(HttpMethod.Post, $"v2/servers/{serverId}/backups", request ?? throw new ArgumentNullException(nameof(request)), "action", cancellationToken); + + /// + public Task> ListKernelsAsync(long serverId, PageRequest? page = null, CancellationToken cancellationToken = default) => + GetPageAsync($"v2/servers/{serverId}/kernels", "kernels", page, null, cancellationToken); + + /// + public Task> ListSnapshotsAsync(long serverId, PageRequest? page = null, CancellationToken cancellationToken = default) => + GetPageAsync($"v2/servers/{serverId}/snapshots", "snapshots", page, null, cancellationToken); + + /// + public Task> GetThresholdAlertsAsync(long serverId, CancellationToken cancellationToken = default) => + GetItemAsync>($"v2/servers/{serverId}/threshold_alerts", "threshold_alerts", cancellationToken); + + /// + public Task> GetThresholdAlertServerIdsAsync(CancellationToken cancellationToken = default) => + GetItemAsync>("v2/servers/threshold_alerts", "server_ids", cancellationToken); + + /// + public Task> ListSoftwareAsync(long serverId, PageRequest? page = null, CancellationToken cancellationToken = default) => + GetPageAsync($"v2/servers/{serverId}/software", "licensed_software", page, null, cancellationToken); + + /// + public Task GetUserDataAsync(long serverId, CancellationToken cancellationToken = default) => + GetDirectItemAsync($"v2/servers/{serverId}/user_data", cancellationToken); + + /// + public Task GetConsoleAsync(long serverId, CancellationToken cancellationToken = default) => + GetItemAsync($"v2/servers/{serverId}/console", "console", cancellationToken); +} diff --git a/src/BinaryLane.Api/Resources/SizesApi.cs b/src/BinaryLane.Api/Resources/SizesApi.cs new file mode 100644 index 0000000..39d5977 --- /dev/null +++ b/src/BinaryLane.Api/Resources/SizesApi.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using BinaryLane.Api.V2.Http; +using BinaryLane.Api.V2.Models; +using BinaryLane.Api.V2.Pagination; + +namespace BinaryLane.Api.V2.Resources; + +/// Lists available server sizes. +public interface ISizesApi +{ + Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default); + IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default); +} + +/// +public sealed class SizesApi : BinaryLaneResourceBase, ISizesApi +{ + /// Initializes the sizes resource. + public SizesApi(IBinaryLaneApiExecutor executor, BinaryLaneJsonSerializerOptions json) + : base(executor, json) + { + } + + /// + public Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => + GetPageAsync("v2/sizes", "sizes", page, null, cancellationToken); + + /// + public IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => + GetAllPagesAsync("v2/sizes", "sizes", page, null, cancellationToken); +} diff --git a/src/BinaryLane.Api/Resources/SoftwareApi.cs b/src/BinaryLane.Api/Resources/SoftwareApi.cs new file mode 100644 index 0000000..0f80176 --- /dev/null +++ b/src/BinaryLane.Api/Resources/SoftwareApi.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using BinaryLane.Api.V2.Http; +using BinaryLane.Api.V2.Models; +using BinaryLane.Api.V2.Pagination; + +namespace BinaryLane.Api.V2.Resources; + +/// Lists available licensed software and operating-system software. +public interface ISoftwareApi +{ + Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default); + IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default); + Task GetAsync(long softwareId, CancellationToken cancellationToken = default); + Task> ListOperatingSystemAsync(string operatingSystemIdOrSlug, PageRequest? page = null, CancellationToken cancellationToken = default); +} + +/// +public sealed class SoftwareApi : BinaryLaneResourceBase, ISoftwareApi +{ + /// Initializes the software resource. + public SoftwareApi(IBinaryLaneApiExecutor executor, BinaryLaneJsonSerializerOptions json) + : base(executor, json) + { + } + + /// + public Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => + GetPageAsync("v2/software", "software", page, null, cancellationToken); + + /// + public IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => + GetAllPagesAsync("v2/software", "software", page, null, cancellationToken); + + /// + public Task GetAsync(long softwareId, CancellationToken cancellationToken = default) => + GetItemAsync($"v2/software/{softwareId}", "software", cancellationToken); + + /// + public Task> ListOperatingSystemAsync(string operatingSystemIdOrSlug, PageRequest? page = null, CancellationToken cancellationToken = default) => + GetPageAsync( + $"v2/software/operating_system/{EscapePathSegment(operatingSystemIdOrSlug)}", + "software", + page, + null, + cancellationToken); +} diff --git a/src/BinaryLane.Api/Resources/SshKeysApi.cs b/src/BinaryLane.Api/Resources/SshKeysApi.cs new file mode 100644 index 0000000..b584884 --- /dev/null +++ b/src/BinaryLane.Api/Resources/SshKeysApi.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using BinaryLane.Api.V2.Http; +using BinaryLane.Api.V2.Models; +using BinaryLane.Api.V2.Pagination; + +namespace BinaryLane.Api.V2.Resources; + +/// Manages account SSH keys. +public interface ISshKeysApi +{ + Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default); + IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default); + Task GetAsync(long keyId, CancellationToken cancellationToken = default); + Task CreateAsync(SshKeyRequest request, CancellationToken cancellationToken = default); + Task UpdateAsync(long keyId, UpdateSshKeyRequest request, CancellationToken cancellationToken = default); + Task DeleteAsync(long keyId, CancellationToken cancellationToken = default); +} + +/// +public sealed class SshKeysApi : BinaryLaneResourceBase, ISshKeysApi +{ + /// Initializes the SSH-key resource. + public SshKeysApi(IBinaryLaneApiExecutor executor, BinaryLaneJsonSerializerOptions json) + : base(executor, json) + { + } + + /// + public Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => + GetPageAsync("v2/account/keys", "ssh_keys", page, null, cancellationToken); + + /// + public IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => + GetAllPagesAsync("v2/account/keys", "ssh_keys", page, null, cancellationToken); + + /// + public Task GetAsync(long keyId, CancellationToken cancellationToken = default) => + GetItemAsync($"v2/account/keys/{keyId}", "ssh_key", cancellationToken); + + /// + public Task CreateAsync(SshKeyRequest request, CancellationToken cancellationToken = default) => + SendItemAsync(HttpMethod.Post, "v2/account/keys", request ?? throw new ArgumentNullException(nameof(request)), "ssh_key", cancellationToken); + + /// + public Task UpdateAsync(long keyId, UpdateSshKeyRequest request, CancellationToken cancellationToken = default) => + SendItemAsync(HttpMethod.Put, $"v2/account/keys/{keyId}", request ?? throw new ArgumentNullException(nameof(request)), "ssh_key", cancellationToken); + + /// + public Task DeleteAsync(long keyId, CancellationToken cancellationToken = default) => + Executor.DeleteAsync($"v2/account/keys/{keyId}", null, null, cancellationToken); +} diff --git a/src/BinaryLane.Api/Resources/VpcsApi.cs b/src/BinaryLane.Api/Resources/VpcsApi.cs new file mode 100644 index 0000000..91817fb --- /dev/null +++ b/src/BinaryLane.Api/Resources/VpcsApi.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using BinaryLane.Api.V2.Http; +using BinaryLane.Api.V2.Models; +using BinaryLane.Api.V2.Pagination; + +namespace BinaryLane.Api.V2.Resources; + +/// Manages private virtual networks and their members. +public interface IVpcsApi +{ + Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default); + IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default); + Task GetAsync(long vpcId, CancellationToken cancellationToken = default); + Task CreateAsync(CreateVpcRequest request, CancellationToken cancellationToken = default); + Task ReplaceAsync(long vpcId, UpdateVpcRequest request, CancellationToken cancellationToken = default); + Task UpdateAsync(long vpcId, PatchVpcRequest request, CancellationToken cancellationToken = default); + Task DeleteAsync(long vpcId, CancellationToken cancellationToken = default); + Task> ListMembersAsync(long vpcId, PageRequest? page = null, CancellationToken cancellationToken = default); +} + +/// +public sealed class VpcsApi : BinaryLaneResourceBase, IVpcsApi +{ + /// Initializes the VPC resource. + public VpcsApi(IBinaryLaneApiExecutor executor, BinaryLaneJsonSerializerOptions json) + : base(executor, json) + { + } + + /// + public Task> ListAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => + GetPageAsync("v2/vpcs", "vpcs", page, null, cancellationToken); + + /// + public IAsyncEnumerable ListAllAsync(PageRequest? page = null, CancellationToken cancellationToken = default) => + GetAllPagesAsync("v2/vpcs", "vpcs", page, null, cancellationToken); + + /// + public Task GetAsync(long vpcId, CancellationToken cancellationToken = default) => + GetItemAsync($"v2/vpcs/{vpcId}", "vpc", cancellationToken); + + /// + public Task CreateAsync(CreateVpcRequest request, CancellationToken cancellationToken = default) => + SendItemAsync(HttpMethod.Post, "v2/vpcs", request ?? throw new ArgumentNullException(nameof(request)), "vpc", cancellationToken); + + /// + public Task ReplaceAsync(long vpcId, UpdateVpcRequest request, CancellationToken cancellationToken = default) => + SendItemAsync(HttpMethod.Put, $"v2/vpcs/{vpcId}", request ?? throw new ArgumentNullException(nameof(request)), "vpc", cancellationToken); + + /// + public Task UpdateAsync(long vpcId, PatchVpcRequest request, CancellationToken cancellationToken = default) => + SendItemAsync(BinaryLaneHttpMethods.Patch, $"v2/vpcs/{vpcId}", request ?? throw new ArgumentNullException(nameof(request)), "vpc", cancellationToken); + + /// + public Task DeleteAsync(long vpcId, CancellationToken cancellationToken = default) => + Executor.DeleteAsync($"v2/vpcs/{vpcId}", null, null, cancellationToken); + + /// + public Task> ListMembersAsync(long vpcId, PageRequest? page = null, CancellationToken cancellationToken = default) => + GetPageAsync($"v2/vpcs/{vpcId}/members", "members", page, null, cancellationToken); +} diff --git a/tests/BinaryLane.Api.Tests/ModelSerializationTests.cs b/tests/BinaryLane.Api.Tests/ModelSerializationTests.cs index 46b613e..b2eb574 100644 --- a/tests/BinaryLane.Api.Tests/ModelSerializationTests.cs +++ b/tests/BinaryLane.Api.Tests/ModelSerializationTests.cs @@ -1,3 +1,5 @@ +using System; +using System.Linq; using System.Text.Json; using BinaryLane.Api.V2.Http; using BinaryLane.Api.V2.Models; @@ -146,4 +148,27 @@ public sealed class ModelSerializationTests Assert.NotNull(future.AdditionalProperties); Assert.Equal("kept", future.AdditionalProperties!["provider_option"].GetString()); } + + [Fact] + public void EveryConcreteServerActionRoundTripsThroughItsProviderDiscriminator() + { + var actionTypes = typeof(ServerAction).Assembly + .GetTypes() + .Where(type => + type.IsSealed && + type.IsSubclassOf(typeof(ServerAction)) && + type.GetConstructor(Type.EmptyTypes) is not null) + .OrderBy(type => type.Name, StringComparer.Ordinal); + + foreach (var actionType in actionTypes) + { + var action = (ServerAction)Activator.CreateInstance(actionType)!; + string json = JsonSerializer.Serialize(action, Json); + ServerAction? deserialized = JsonSerializer.Deserialize(json, Json); + + Assert.NotNull(deserialized); + Assert.Equal(actionType, deserialized.GetType()); + Assert.Equal(action.Type, deserialized.Type); + } + } }