tailscale-rest 1.3.2

Typed client for the Tailscale control-plane REST API v2
Documentation
//! Services: a name and a pair of addresses that several devices can host.

use crate::model;
use crate::models::KnownValues;

/// How far a device hosting a service has got through approval.
///
/// The two `approved:` values differ only in how the approval happened, which
/// is why this is one string and not a boolean and a flag.
pub const APPROVAL_LEVELS: &[&str] = &["not-approved", "approved:auto", "approved:manual"];

pub const KNOWN_VALUES: &[KnownValues] = &[("ServiceHostInfo.approvalLevel", APPROVAL_LEVELS)];

model! {
    /// A service, as the tailnet sees it.
    VipServiceInfo as "VIPServiceInfo" {
        /// Unique within the tailnet.
        name: "name" => String,
        /// A label for the admin console and for clients with access. At most
        /// 64 characters.
        display_name: "displayName" => String,
        /// The IPv4 first, then the IPv6.
        addrs: "addrs" => Vec<String>,
        comment: "comment" => String,
        /// `protocol:port` pairs, where `tcp` is the only protocol so far.
        /// `do-not-validate` skips the check.
        ports: "ports" => Vec<String>,
        tags: "tags" => Vec<String>,
    }

    /// The body a `PUT` sends, which is the same six fields.
    ///
    /// The description declares it separately to re-describe `addrs`, which on
    /// the way in is a request rather than a report: unset or one IPv4 for a
    /// new service, and for an existing one an IPv4 that may be changed
    /// alongside an IPv6 that may not.
    VipServiceInfoPut as "VIPServiceInfoPut" is VipServiceInfo;

    /// One device hosting a service.
    ServiceHostInfo {
        stable_node_id: "stableNodeID" => String,
        /// One of [`APPROVAL_LEVELS`].
        approval_level: "approvalLevel" => String,
        configured: "configured" => String,
    }

    /// Whether a device may host a service, and how it got there.
    VipServiceApproval as "VIPServiceApproval" {
        approved: "approved" => bool,
        /// `true` where an auto-approver did it rather than a person.
        auto_approved: "autoApproved" => bool,
    }

    // -----------------------------------------------------------------------
    // The shapes the routes carry.
    // -----------------------------------------------------------------------

    /// Every service the tailnet advertises.
    ///
    /// `vipServices` rather than `services`, which is the envelope keeping the
    /// Go client's spelling where the path does not — see the drift test's
    /// note on the two names.
    VipServiceList as "GET /tailnet/{tailnet}/services 200" {
        vip_services: "vipServices" => Vec<VipServiceInfo>,
    }

    /// The devices standing behind one service.
    ServiceHostList as "GET /tailnet/{tailnet}/services/{serviceName}/devices 200" {
        hosts: "hosts" => Vec<ServiceHostInfo>,
    }

    /// What approving or unapproving one host sends.
    ServiceApprovalRequest
        as "POST /tailnet/{tailnet}/services/{serviceName}/device/{deviceId}/approved body" {
        approved: "approved" => bool,
    }
}