//! All responses which are recieved by this application from the Lunanode API. //! These responses are all strictly typed, and documented. Although in some cases it is noted that //! it should have an even stricter type, or that the field meaning is unkown. use crate::success; use crate::external; use crate::types::{ LunaNodeResponse, }; use clap; use lunanode_macros::lunanode_response; use serde::{Serialize, Deserialize}; use serde_with::{ DisplayFromStr, serde_as, }; #[serde_as] #[derive(Serialize, Deserialize, PartialEq, Debug)] /// Defines a VM (used for requests using the VM section) pub struct VirtualMachine { /// the UUID of the VM vm_id: String, // should be UUIDv4 /// the name of the VM set by the user name: String, // the name set by the user #[serde_as(as="DisplayFromStr")] /// The plan ID, cross-reference with /plan/list/ plan_id: i32, // should be more strict /// The hostname set by the user hostname: String, // the hostname set by the user #[serde(rename="primaryip")] /// The primary (public) IP address of the VM. primary_ip: std::net::Ipv4Addr, #[serde(rename="privateip")] /// The private IP address of the VM. private_ip: std::net::Ipv4Addr, #[serde_as(as="DisplayFromStr")] /// RAM of the VM in GB ram: i32, // in GB, may need to be a float #[serde_as(as="DisplayFromStr")] /// The number of virtual CPU cores vcpu: i32, // CPU cores #[serde_as(as="DisplayFromStr")] /// The storage amount of the VM in GB storage: i32, // in GB #[serde_as(as="DisplayFromStr")] /// bandwidth in GB/month bandwidth: i32, // in GB/month /// The region where the VM is located region: LNRegion, // could be more strict /// The status, which should be more strict than a String. os_status: String, // should be nmore strict } #[lunanode_response] /// The result of requesting a list of VMs on the user's Lunanode account. /// See also: [`crate::requests::VmListRequest`] pub struct VmListResponse { /// A list of VMs. vms: Vec, } #[derive(Serialize, Deserialize, Debug)] #[serde(rename_all="lowercase")] /// An enum defining whether an IP is attached to a VM or is simply allocated without being /// attached to any VM in particular. /// See also: [`FloatingIp`] enum AttachmentType { /// An unattached floating IP. Unattached, /// An attached floating IP. Vm, } #[serde_as] #[derive(Serialize, Deserialize, Debug)] /// Detailed information about a floating IP struct FloatingIp { /// A String with a VM UUID if attached, otherwise None. attached_id: Option, /// A String with the VM's name if attached, otherwise None. attached_name: Option, /// Vm/Unattached attached_type: AttachmentType, /// The hostname of the floating IP address, usually something like /// xxx-xxx-xxx-xxx.rdns.lunanode.com hostname: String, /// The IP address of the floating IP. ip: std::net::Ipv4Addr, /// The region in which the IP address has been allocated. region: LNRegion, /// The rDNS domain, if specified, otherwise, None. reverse: Option, #[serde_as(as="DisplayFromStr")] /// The last time the record was updated. time_updated: chrono::DateTime, } #[serde_as] #[derive(Serialize, Deserialize, Debug)] /// Extra detailed information for a VM. pub struct VMInfoExtra { #[serde_as(as="DisplayFromStr")] /// bandwidth allowed over a month in GB bandwidth: i32, /// the hostname set by the user hostname: String, // sufficiently vague /// the name set by the user name: String, // sufficiently vague /// the status of the operating system; possible values: "active", ... TODO os_status: String, // should be stricter #[serde_as(as="DisplayFromStr")] /// id of the plan being used on the VM plan_id: i32, #[serde(rename="primaryip")] /// primary (floating) IP primary_ip: std::net::Ipv4Addr, #[serde(rename="privateip")] /// the private (non-floating) IP to connect between nodes private_ip: std::net::Ipv4Addr, #[serde_as(as="DisplayFromStr")] /// RAM meassured in MB ram: i32, /// the datacentre location the VM is running in region: LNRegion, #[serde_as(as="DisplayFromStr")] /// the storage size of the VM in GB storage: i32, #[serde_as(as="DisplayFromStr")] /// number of virtual CPU cores allocated to the VM vcpu: i32, #[serde_as(as="DisplayFromStr")] /// UUIDv4 of the VM vm_id: String, } #[derive(Serialize, Deserialize, Debug)] #[serde(untagged)] /// A generic IP address type, with two variants: V4, and V6. This is used for generic types returned from the API. For example, a list of IP addresses without the IP type specified. pub enum IPAddress { /// IPv4 variant V4(std::net::Ipv4Addr), /// IPv6 variant V6(std::net::Ipv6Addr), } #[derive(Serialize, Deserialize, Debug)] /// An IP address type enum, specifying either V4 or V6. pub enum IPAddressType { #[serde(rename="4")] /// IPv4 variant V4, #[serde(rename="6")] /// IPv6 variant V6, } #[derive(Serialize, Deserialize, Debug)] /// VM IP address pub struct VMAddress { /// The IP address of the VM. addr: IPAddress, #[serde(with="external")] /// Whether the IP is an internal or external kind. external: bool, /// The version of IP address used. version: IPAddressType, #[serde(rename="reverse")] /// The reverse DNS assigned to the VM, if specified. Otherwise, None. rdns: Option, } #[serde_as] #[derive(Serialize, Deserialize, Debug)] /// Detailed VM info. pub struct VMInfo { #[serde(rename="additionalip")] /// A list of additional IPs (which are not the primary IP) which have been assigned to the VM. additional_ip: Vec, #[serde(rename="additionalprivateip")] /// Any additional private IPs assigned to the VM. additional_private_ip: Vec, /// A list of addresses inherently part of the VM. Think of a primary private IP, or where /// outgoing internet traffic is routed. addresses: Vec, /// a possibly empty string containing an error message error_detail: Option, /// some unkown string that doesn't seem to be a UUID... maybe the checksum? host_id: String, /// the name of the VM set at creation by the user hostname: String, /// the name of the image being used by the VM image: String, /// the primary, external IP of the VM ip: std::net::Ipv4Addr, /// a list of IPv6 addresses assigned to the VM ipv6: Vec, /// Login details from the VM; this could potentially be a bit more strict to support the storing of username and password separately. /// Also, it's optional. The server may not even report this value at all, not only give a blank one. Fair enough. Seems more secure. login_details: Option, /// the operating system (orignal image used to load the machine) os: String, // sufficiently vague #[serde(rename="privateip")] /// the primary private IP assigned to the machine private_ip: std::net::Ipv4Addr, /// security groups by id that the VM belongs to; should be a vec of i32, but it might take some custom implementations security_group_ids: Vec, /// security groups by name that the VM belongs to security_groups: Vec, #[serde(rename="securitygroups")] /// why is there a second one of these with a different name. This is stupid. security_groups2: Vec, /// an HTML status of the machine status: String, /// the color of the status; this could be stricter status_color: String, // could be more strict /// the non-HTML status, this could potentially be more strict status_nohtml: String, /// A raw status-code string; this could for sure be more strict. status_raw: String, /// A possibly empty string, idk what task_state is tho task_state: String, // a possibly empty string /// A possibly empty string of attached volumes. volumes: String, } #[lunanode_response] /// The result from a [`crate::requests::VmInfoRequest`]. pub struct VMInfoResponse { /// Extra information (cached) extra: VMInfoExtra, /// Detailed VM info (uncached) info: VMInfo, } #[derive(Serialize, Deserialize, Debug)] /// A plan category. pub enum PlanCategory { #[serde(rename="Compute-Optimized")] /// For CPU-bound tasks. ComputeOptimized, #[serde(rename="General Purpose")] /// Pretty good for most projects. GeneralPurpose, #[serde(rename="Memory-Optimized")] /// For memory-bound tasks. MemoryOptimized, #[serde(rename="SSD-Cached High-Memory")] /// For IO/memory-bound tasks. SSDCacheHighMemory, #[serde(rename="SSD-Cached Standard")] /// For IO-bound tasks. SSDCacheStandard, } #[derive(Serialize, Deserialize, Debug, Hash, Eq, PartialEq)] #[serde(rename_all = "lowercase")] /// Regions where Lunanode is supported. pub enum LNRegion { /// Montreal, Quebec, Canada. Montreal, /// Roubaix, France. Roubaix, /// Toronto, Ontario, Canada. Toronto } #[serde_as] #[derive(Serialize, Deserialize, Debug)] /// A VM plan/level of serivce. pub struct Plan { #[serde_as(as="DisplayFromStr")] /// Does the plan support all regions? all_regions: i32, // may need to be more strict? #[serde_as(as="DisplayFromStr")] /// The maxmimum bandwidth in Mbps bandwidth: i32, // in Mbps /// Category of plan category: PlanCategory, #[serde_as(as="DisplayFromStr")] /// Lunanode uses a CPU points system to determine how powerful the CPU is. cpu_points: f32, // no idea what this meas /// The name of the plan, set by Lunanode themselves. name: String, // plan name, this could potentially be strictly typed as the types of plans don't often change "s.half", "s.1", "m.1", "m.2", etc. #[serde_as(as="DisplayFromStr")] /// The plan ID. Could be useful if creating a new VM. plan_id: i32, // can be strictly typed, if needed #[serde_as(as="DisplayFromStr")] /// The cost in USD per hour. price: f32, // up to 7 decmial points (f32), and this is the number of US dollars per hour /// The price is USD per month, with a $ attached. price_monthly_nice: String, // instead of calculating it on your own, this provides a nice reading of the price for clients /// The price in USD per hour, with a $ attached. price_nice: String, // same as above, but for the hour #[serde_as(as="DisplayFromStr")] /// The amount of RAM in MB. ram: i32, // in MB /// Regions where the plan can be dpeloyed. regions: Vec, // list of regions by name /// Regions where the plan can be deployed, separated by a comma. regions_nice: String, // list of regions concatonated with commans #[serde_as(as="DisplayFromStr")] /// Storage in GB. storage: i32, // per GB #[serde_as(as="DisplayFromStr")] /// Number of vCPU cores. vcpu: i32, // number of vCPU cores } #[lunanode_response] /// A list of plans from a [`crate::requests::PlanListRequest`] pub struct PlanListResponse { /// List of plans; see [`Plan`] for more detail. plans: Vec, } #[serde_as] #[derive(Serialize, Deserialize, Debug)] /// An ISO or QCOW2 image stored on Lunanode. pub struct Image { #[serde_as(as="DisplayFromStr")] /// ID of the image. This is useful for later if you would like to interact with it in some way. image_id: i32, // id of the image /// Name of the Image set by the user, or Lunanode. name: String, // set by the user or LunaNode /// The region in which the image is stored. region: LNRegion, /// The status of the image; at least "active" and "inactive" are possible. status: String, // should be stricter, at least "active", "inactive"(?) } #[serde_as] #[derive(Serialize, Deserialize, Debug)] /// A storage volume on the user's Lunanode account. pub struct Volume { #[serde_as(as="DisplayFromStr")] /// The personal ID used for the volume. id: i32, #[serde_as(as="DisplayFromStr")] /// the UUID for the volume identification: String, /// the name set by the user name: String, /// The region where the volume is located. region: LNRegion, /// The size of the volume, in GB #[serde_as(as="DisplayFromStr")] size: i32, /// The status of the volume; this should be more string, but for now at least "active". status: String, #[serde_as(as="DisplayFromStr")] /// a datetime (explicitly set to UTC) of when the volume was created time_created: chrono::DateTime, #[serde_as(as="DisplayFromStr")] /// ID of the user who created the volume user_id: i32, } #[serde_as] #[derive(Serialize, Deserialize, Debug)] /// Details of a Lunanode image pub struct ImageDetails { /// This should be more strict. At least one possible value is "writeback". cache_mode: String, // should be stricter, at least "writeback", /// This should be more strict; this should be a strict checksum type. checksum: String, // should be stricter, to check of checksum type /// This should be more strict. At least one possible value is "iso". disk_format: String, // should be stricter, at least "iso" /// This should be more strict. I think the only possible values are "ide" and "sata". hw_disk_bus: String, // should be stricter, at least "ide", /// It's not clear exactly what this means; the Lunanode documentation isn't extremely well done. /// But at least one possible value here is "cirrus"; unsure if other values are possible, or /// what they are. hw_video_model: String, // could, in theory, be stricter, at least: "cirrus", /// The model of the virtual interface (I think) hw_vif_model: String, // appropriately vague /// A read only image? #[serde(with="success")] is_read_only: bool, // "yes"/"no" /// There should not be many possible values, but one of them is "host-model". libvrt_cpu_mode: String, // should be stricter, at least: "host-model", /// Unkown list of metadata. metadata: Vec<()>, // vec of what? /// The name of the image; often set by the user. name: String, // sufficiently vague /// The region of the image. region: LNRegion, // sufficiently typed /// The size of the image in MB. size: i32, // in MB, maybe? /// In theory this could be stricter, but Lunanode does not enumerate all possible return types. /// Possible values are at least: "active". status: String, // should be stricter, at least: "active", #[serde_as(as="DisplayFromStr")] /// An (explicitly UTC) datetime of when the VM was created time_created: chrono::DateTime, // should be a datetime } #[lunanode_response] /// A response from [`crate::requests::ImageDetailRequest`] pub struct ImageDetailResponse { /// Details of a specific image. details: ImageDetails, } #[lunanode_response] /// See also: [`crate::requests::ImageListRequest`] pub struct ImageListResponse { /// List of images and their information. images: Vec, } #[lunanode_response] /// See also: [`crate::requests::BillingCreditRequest`] pub struct BillingCreditResponse { /// Money left in the account in USD #[serde_as(as="DisplayFromStr")] credit: f32, } #[lunanode_response] /// See also: [`crate::requests::VolumeListRequest`] pub struct VolumeListResponse { /// List of volumes and their associated information. volumes: Vec, } #[serde_as] #[derive(Serialize, Deserialize, Debug)] /// A network with a subnet. pub struct Network { /// The name set by the user when creating the network. name: String, #[serde_as(as="DisplayFromStr")] /// The ID of the network; this is useful if you'd like to modify it in another request. net_id: i32, /// The network subnet. This should be strictly typed as an IP address w/ a subnet attached. TODO: subnet type subnet: String, } #[lunanode_response] /// A response from [`crate::requests::NetworkListRequest`] pub struct NetworkListResponse { /// A list of networks. networks: Vec, } #[lunanode_response] /// A response from [`crate::requests::FloatingIpListRequest`] pub struct FloatingIpListResponse { /// A list of [`FloatingIp`]s. ips: Vec, } #[serde_as] #[derive(Serialize, Deserialize, Debug)] /// A domain "zone". This is the same as a root domain. pub struct Zone { #[serde_as(as="DisplayFromStr")] /// The lunanode id of the zone. id: i32, /// The domain (or subdomain) being managed by the zone. name: String, /// The default TTL used for this zone. This can be overridden manually when specifying new records. #[serde_as(as="DisplayFromStr")] ttl: i32, } #[lunanode_response] /// A response from [`crate::requests::ZoneListRequest`] pub struct ZoneListResponse { /// A map of all zones, with their IDs as their keys. zones: std::collections::HashMap, } #[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq, Hash, clap::ValueEnum)] #[serde(rename="UPPERCASE")] /// Possible record types for [`Record`] pub enum RecordType { /// An A record is an IPv4 pointer with a key (domain or subdomain) and value (IP address). A, /// An AAAA record (usually said "quadrupal A") is an IPv6 pointer with a key (domain or subdomain) and /// value (IP address). AAAA, /// A CAA record is a way to restrict which authorities may create TLS certificates for your domain. Best security practices state that you should set this for any domain you have sufficient control over. CAA, /// A CNAME record basically forwards requests from a domain or subdomain to a second domain or /// subdomain. It is very common to see this in places where www.example.com and ftp.example.com /// use the same server (and IP address) at example.com; now, when switching IP addresses, the address only /// needs to be updated for example.com, and all the subdomains will still function like normal. CNAME, /// An ALIAS record states that writing a domain one way, for example: ca.example.com, is the /// same as another, for example: canada.example.com. ALIAS, /// An MX record tells email providers where to send incoming mail. MX, /// An NS record decides the nameserver record for the domain. This is necessary to use in the /// case of Lunanode, since you cannot purchase a domain through them. You must purchase the /// domain elsewhere, then set your NS records at your registrar to point to lunanode's /// nameservers. NS, /// A TXT record is a static record generally used for verification of some kind or another. Some /// email providers (ProtonMail), will require you to set up a TXT record to prove that you own /// the domain. TXT, /// An SPF record is a deprecated form of email authentication record. SPF, /// An SRV record can be used so that a port is not necessary when running multiple (similar or /// the same) services on different ports. For example, suppose you run two web servers, one at /// 80 and 443 (standard HTTP and HTTPS ports) and one on 8080 and 4443 (commonly used in live /// updating prototypes. An SRV record can help you use a subdomain instead of a port number /// at the end of the domain. So beta.example.com and www.example.com could point a browser to /// different ports of the same IP. SRV } #[serde_as] #[derive(Serialize, Deserialize, Debug)] /// A DNS record. pub struct Record { /// The record id #[serde_as(as="DisplayFromStr")] id: i32, /// The record type, one of A, AAAA, CNAME, ALIAS, MX, NS, TXT, SPF, SRV #[serde(rename="type")] record_type: RecordType, /// The name of the record (for example, if setting an ip address for example.org, this field would show: example.org." name: String, /// The data assigned to this record. It shoudl always be a IPv4/v6 address, unless it's an NS data: String, #[serde_as(as="DisplayFromStr")] /// The auxiliary value, only used on some record types. aux: i32, #[serde_as(as="DisplayFromStr")] /// The TTL for the record. ttl: i32, /// Unknown value policy: String, /// The region the record applies to, if specificed. Otherwise None. Currently a String due to type issues. region: String, #[serde(rename="regiongroup")] /// This value can be any region group defined by the user or auto. This could be stricter. region_group: String, /// This value can be either Canada or France, and it should be stricter. country: String, /// The continent as set by the user for this record. May be none or auto. continent: String, #[serde_as(as="DisplayFromStr")] /// Is the record for everywhere (global); this should be a bool global: i32, #[serde_as(as="DisplayFromStr")] /// The latitude of the record, if given. latitude: f32, #[serde_as(as="DisplayFromStr")] /// Longitude of a record, if given. longitude: f32, #[serde(with="external")] /// Is active in inactive record. status: bool, #[serde_as(as="DisplayFromStr")] /// Monitor id, if given. monitor_id: i32, /// Optional check name? check_name: Option, /// The "nice" version of the status as a string. status_nice: String, } #[lunanode_response] /// The result of requesting all DNS records for a domain. /// See also: [`crate::requests::RecordListRequest`], [`ZoneListResponse`] pub struct RecordListResponse { records: std::collections::HashMap, } #[serde_as] #[derive(Serialize, Deserialize, Debug)] /// A detailed dyn record. pub struct DynRecord { #[serde_as(as="DisplayFromStr")] /// An id you may need later to edit this. /// See also: [`DynUpdateResponse`], [`DynRemoveResponse`] id: i32, /// The name, or key (usually a subddomain) of the dyn record. name: String, /// An IP address (a value). ip: IPAddress, } #[lunanode_response] /// The result of requesting all dyn records on a domain. /// See also: [`crate::requests::DynListRequest`] pub struct DynListResponse { dyns: std::collections::HashMap, } #[serde_as] #[derive(Serialize, Deserialize, Debug)] /// Detailed information about an SSH key. /// See also: [`SshKeyResponse`] pub struct SshKey { #[serde_as(as="DisplayFromStr")] id: i32, /// Name of key, as specified by the user. name: String, /// The value of the SSH key; this is not more strict, only because the value is meant to be literal and not a "structured" representation of an SSH key. In addition, this would take a lot of extra boilerplate. value: String, } #[lunanode_response] /// The result of requesting a list of all regions. /// See also: [`crate::requests::RegionListRequest`] pub struct RegionListResponse { /// A map of all regions supported by Lunanode. regions: std::collections::HashMap, } #[lunanode_response] /// The result of requesting all ssh keys connected to an account. /// See also: [`crate::requests::SshKeyRequest`] pub struct SshKeyResponse { #[serde(flatten)] /// List of keys stored in the LunaNode cloud. The String is just an index that I can't get to flatten :grumpy programmer noises: keys: std::collections::HashMap, } #[lunanode_response] /// The reuslt of requesting email usage statistics from Lunanode. pub struct EmailUsageResponse { #[serde_as(as="DisplayFromStr")] /// The number of domains being used by the account. domains: i32, #[serde_as(as="DisplayFromStr")] /// Usage of email in bytes. storage: i32, /// Usage of email in GB with GB appended to the end of the string, storage_nice: String, #[serde_as(as="DisplayFromStr")] messages: i32, } #[serde_as] #[derive(Serialize, Deserialize, Debug)] /// The result of requesting an email's domain information. pub struct EmailDomainInfo { #[serde_as(as="DisplayFromStr")] /// An id for the domain's email info. This will be useful later if you want to change /// information about how the email domain operates. id: i32, /// A String of the domain. name: String, /// Storage used storage: String, /// Storage used in MB/GB, with " MB/GB" attached. storage_nice: String, } #[lunanode_response] /// The result of requesting a list of email domains on the Lunanode account. pub struct EmailDomainListResponse { #[serde(flatten)] /// Key/value pairs where the key is a String of the domain. domains: std::collections::HashMap, } #[lunanode_response] /// The result of requesting all monitor checks (active or inactive). /// See also: [`crate::requests::MonitorCheckListRequest`] pub struct MonitorCheckListResponse { /// This is not done yet. A Check type will be required. TODO checks: Vec, } #[derive(Serialize, Deserialize, Debug)] #[serde(untagged)] /// The type of parameter being asked for by the monitor check. /// See also: [`Param`] pub enum ParamType { /// A single, simple parameter. Single(String), /// Posssible options in the case of a fixed set of choices. Generally speaking, the key/value /// Strings will be the same, unless the choice has a space or some other character that would /// make it annoying to parse over an HTTP request. Options(std::collections::HashMap), } #[derive(Serialize, Deserialize, Debug)] /// Detailed information about a parameter of a monitor check. /// See also [`MonitorTypes`] pub struct Param { #[serde(with="external")] /// Is the parameter required when creating this monitor check. required: bool, /// What kind of parameter is this. r#type: ParamType, /// The name of the parameter, this would be the name of a field in a request. name: String, /// A placeholder, or example of what may by used in this parameter. placeholder: Option, } #[derive(Serialize, Deserialize, Debug)] /// Detailed information about various monitor types in a category. /// See also: [`MonitorCheckTypesResponse`] pub struct MonitorTypes { /// The name of the monitor type. name: String, /// The short name of the monitor type. short_name: String, /// A list of parameters for the given monitor type. params: std::collections::HashMap } #[lunanode_response] /// The result of asking for possible monitor check types. /// See also: [`crate::requests::MonitorCheckTypesRequest`] pub struct MonitorCheckTypesResponse { /// All possible monitor check types as supported by Lunanode. /// Note that the String key matches a category name, and all monitor types under that category /// will be listed under each. types: std::collections::HashMap, } #[derive(Serialize, Deserialize, Debug)] #[serde(rename_all="lowercase")] /// The type of contact as stated by lunanode as possible options. This type helps decide how to /// use the contact in the case of a monitor trip. /// See also: [`Contact`] pub enum ContactType { /// A (presumably) valid email. Email, /// A (presumably) valid SMS-captable phone or VOIP number. Sms, /// A (presumably) valid voice-captable phone or VOIP number. Voice, /// A (presumably) valid HTTP(S) URL. Http, } #[serde_as] #[derive(Serialize, Deserialize, Debug)] /// A contact for monitoring purposes. /// See also: [`Contacts`], [`MonitorContactListResponse`] pub struct Contact { #[serde_as(as="DisplayFromStr")] id: i32, r#type: ContactType, data: String, } #[derive(Serialize, Deserialize, Debug)] #[serde(untagged)] /// Possible values for contacts listed in Lunanode. This is required because what the API sends /// back an empty list when there are no contacts, but a hashmap if there is one or more contacts. pub enum Contacts { /// Need an empty vec of some kind to hold the blank value, which appears as []. Empty(Vec), /// Note that this HashMap should be indexed by i32, not String. This is a limitation of serde as far as I can tell. Populated(std::collections::HashMap), } #[lunanode_response] /// The result of requesting a contact list for monitoring purposes. /// See also: [`crate::requests::MonitorContactListRequest`] pub struct MonitorContactListResponse { /// A list of contacts in your LunaNode account. This should be deserialized as Option>, but I haven't gotten around to serializing this in that way. TODO. contacts: Contacts, } #[serde_as] #[derive(Serialize, Deserialize, Debug)] /// An email user on the Lunanode email system. pub struct EmailUser { /// The user's ID. #[serde_as(as="DisplayFromStr")] id: i32, /// The user's email. This may be more strict in the future. email: String, #[serde_as(as="DisplayFromStr")] /// The user's storage usage in MB. storage: i32, /// The user's storage usage, with an "MB" or "GB" designation afterwards. storage_nice: String, } #[lunanode_response] /// The result of requesting a list of email users in a certain domain. /// See also: [`crate::requests::EmailUserListRequest`] pub struct EmailUserListResponse { #[serde(flatten)] /// The users of a domain's email. The String is an id (and should be an i32 TODO). users: std::collections::HashMap, } #[lunanode_response] /// The result of sending a start command to a VM. /// See also: [`crate::requests::VmStartRequest`] pub struct VmStartResponse {} #[lunanode_response] /// The result of sending a stop command to a VM. /// See also: [`crate::requests::VmStopRequest`] pub struct VmStopResponse {} #[lunanode_response] /// The result of sending a reboot command to a VM. /// See also: [`crate::requests::VmRebootRequest`] pub struct VmRebootResponse {} #[lunanode_response] /// The result of adding an email user to a domain. /// See also: [`crate::requests::EmailUserAddRequest`] pub struct EmailUserAddResponse {} #[lunanode_response] /// The result of removing an email user from a domain. /// See also: [`crate::requests::EmailUserRemoveRequest`] pub struct EmailUserRemoveResponse {} #[lunanode_response] /// The result of setting an email user's password in the specified domain. /// See also: `EmailUserSetPasswordRequest` pub struct EmailUserSetPasswordResponse {} #[serde_as] #[derive(Serialize, Deserialize, Debug)] /// A VM-specific IP pub struct VmIp { floating: std::net::Ipv4Addr, /// A network UUID network: String, #[serde_as(as="DisplayFromStr")] network_id: i32, /// Port UUID? What is this? port: String, /// This is an ip/subnet pair, so it could/should be stricter. subnet: String, } #[lunanode_response] /// The result of querying for a list of ips in a specific VM. /// See also: [`crate::requests::VmIpListRequest`] pub struct VmIpListResponse { ips: std::collections::HashMap, } #[lunanode_response] /// the result of removing a dynamic record. /// See also: [`crate::requests::DynRemoveRequest`] pub struct DynRemoveResponse {} #[lunanode_response] /// the result of adding a dynamic record. /// See also: [`crate::requests::DynAddRequest`] pub struct DynAddResponse {} #[lunanode_response] /// the result of adding a zone. /// See also: [`crate::requests::ZoneAddRequest`] pub struct ZoneAddResponse {} #[lunanode_response] /// the result of removing a zone. /// See also: [`crate::requests::ZoneRemoveRequest`] pub struct ZoneRemoveResponse {} #[lunanode_response] /// The result of adding a new record. /// See also: [`crate::requests::RecordAddRequest`] pub struct RecordAddResponse {} #[lunanode_response] /// The result of remove a DNS record. /// See also: [`crate::requests::RecordRemoveRequest`] pub struct RecordRemoveResponse {} #[lunanode_response] /// The result of remove a DNS record. /// See also: [`crate::requests::RecordRemoveRequest`] pub struct EmailDomainAddResponse {} #[lunanode_response] /// The result of remove a DNS record. /// See also: [`crate::requests::RecordRemoveRequest`] pub struct EmailDomainRemoveResponse {} #[serde_as] #[derive(Serialize, Deserialize, Debug)] /// A single email alias pub struct EmailAlias { #[serde_as(as="DisplayFromStr")] /// email alias id for a given domain; this needs to be used in conjunction with a domain ID to do anything useful. id: i32, /// The source address of the email (blank for catch-all). source: String, /// Where the final address is (this may be external). destination: String, } #[lunanode_response] /// The result of listing email aliases. /// See also: [`crate::requests::EmailAliasListRequest`] pub struct EmailAliasListResponse { #[serde(flatten)] aliases: std::collections::HashMap, } #[lunanode_response] /// The result of adding a new email alias. /// See also: [`crate::requests::EmailAliasListRequest`] pub struct EmailAliasAddResponse {} #[lunanode_response] /// The result removing an email alias. /// See also: [`crate::requests::EmailAliasListRequest`] pub struct EmailAliasRemoveResponse {} #[lunanode_response] /// The result setting a DKIM key for a email domain. /// See also: [`crate::requests::EmailDomainListRequest`] pub struct EmailDomainDkimSetResponse {} #[lunanode_response] /// The result removing an email domain's DKIM key. /// See also: [`crate::requests::EmailDomainListRequest`] pub struct EmailDomainDkimUnsetResponse {}