Skip to main content

transip_execute/
lib.rs

1use std::{mem::size_of, time::Duration};
2
3use serde::{Serialize, Serializer};
4pub use transip::configuration_from_environment;
5use transip::{Configuration, api::email::MailForwardInsert};
6pub use transip::{Error, Result};
7use transip_command::{
8    DnsCommand, DomainCommand, EmailBoxCommand, EmailForwardCommand, InvoiceCommand, OnError,
9    ProductCommand, VpsCommand,
10};
11
12// reexport TransipCommand
13pub use transip_command::{ErrorKind, SubCommand, TransipCommand};
14
15pub struct Client {
16    inner: transip::Client,
17    onerror: transip_command::OnError,
18}
19
20impl Client {
21    pub fn exit_on_error(&self) -> bool {
22        self.onerror == OnError::Exit
23    }
24}
25
26trait Report {
27    fn report(self, s: impl Serializer) -> Result<()>;
28}
29
30impl<T: Serialize> Report for Result<T> {
31    fn report(self, s: impl Serializer) -> Result<()> {
32        self.map(|result| {
33            if size_of::<T>() > 0 {
34                result.serialize(s).unwrap();
35            }
36        })
37    }
38}
39
40impl TryFrom<Box<dyn Configuration>> for Client {
41    type Error = transip::Error;
42
43    fn try_from(configuration: Box<dyn Configuration>) -> Result<Self> {
44        transip::Client::try_from(configuration).map(|client| Client {
45            inner: client,
46            onerror: OnError::Print,
47        })
48    }
49}
50
51impl Client {
52    fn execute_dns(&mut self, command: &DnsCommand, s: impl Serializer) -> Result<()> {
53        use transip::api::dns::{DnsApi, DnsEntry};
54        match command {
55            DnsCommand::AcmeValidationDelete { domain } => self
56                .inner
57                .dns_entry_delete_all(domain, DnsEntry::is_acme_challenge)
58                .report(s),
59            DnsCommand::List { domain } => self.inner.dns_entry_list(domain).report(s),
60            DnsCommand::Delete(dns_entry) => {
61                let entry = DnsEntry {
62                    name: dns_entry.name.clone(),
63                    expire: dns_entry.ttl,
64                    entry_type: format!("{:?}", dns_entry.r#type),
65                    content: dns_entry.content.clone(),
66                };
67                self.inner
68                    .dns_entry_delete(&dns_entry.domain, entry)
69                    .report(s)
70            }
71            DnsCommand::Insert(dns_entry) => {
72                let entry = DnsEntry {
73                    name: dns_entry.name.clone(),
74                    expire: dns_entry.ttl,
75                    entry_type: format!("{:?}", dns_entry.r#type),
76                    content: dns_entry.content.clone(),
77                };
78                self.inner
79                    .dns_entry_insert(&dns_entry.domain, entry)
80                    .report(s)
81            }
82            DnsCommand::AcmeValidationSet { domain, challenge } => self
83                .inner
84                .dns_entry_delete_all(domain, DnsEntry::is_acme_challenge)
85                .and_then(|_| {
86                    self.inner
87                        .dns_entry_insert(domain, DnsEntry::new_acme_challenge(60, challenge))
88                })
89                .report(s),
90            #[cfg(feature = "propagation")]
91            DnsCommand::AcmeValidationCheck { domain, challenge } => {
92                acme_validation_propagation::wait(domain, challenge)
93                    .map_err(|_| Error::AcmeChallege)
94            }
95        }
96    }
97
98    fn execute_domain(&mut self, command: &DomainCommand, s: impl Serializer) -> Result<()> {
99        use transip::api::domain::DomainApi;
100        match command {
101            DomainCommand::Item { domain } => self.inner.domain_item(domain).report(s),
102            DomainCommand::List => self.inner.domain_list().report(s),
103        }
104    }
105
106    fn execute_email_box(&mut self, command: &EmailBoxCommand, s: impl Serializer) -> Result<()> {
107        use transip::api::email::EmailApi;
108        match command {
109            EmailBoxCommand::Item { domain, id } => self.inner.mailbox_item(domain, id).report(s),
110            EmailBoxCommand::List { domain } => self.inner.mailbox_list(domain).report(s),
111            EmailBoxCommand::Delete { domain, id } => self.inner.mailbox_delete(domain, id),
112            EmailBoxCommand::Insert {
113                domain,
114                username,
115                password,
116                mb_size,
117            } => {
118                let mailbox = transip::api::email::MailboxInsert {
119                    local_part: username.clone(),
120                    max_disk_usage: *mb_size,
121                    password: password.clone(),
122                };
123                self.inner.mailbox_insert(domain, mailbox)
124            }
125        }
126    }
127
128    fn execute_email_forward(
129        &mut self,
130        command: &EmailForwardCommand,
131        s: impl Serializer,
132    ) -> Result<()> {
133        use transip::api::email::EmailApi;
134        match command {
135            EmailForwardCommand::Item { domain, id } => {
136                self.inner.mailforward_item(domain, id).report(s)
137            }
138            EmailForwardCommand::List { domain } => self.inner.mailforward_list(domain).report(s),
139            EmailForwardCommand::Insert {
140                domain,
141                local_part,
142                forward_to,
143            } => {
144                let mail_forward = MailForwardInsert {
145                    local_part: local_part.clone(),
146                    forward_to: forward_to.clone(),
147                };
148                self.inner.mailforward_insert(domain, mail_forward)
149            }
150            EmailForwardCommand::Delete { domain, id } => self.inner.mailforward_delete(domain, id),
151        }
152    }
153
154    fn execute_invoice(&mut self, command: &InvoiceCommand, s: impl Serializer) -> Result<()> {
155        use transip::api::account::AccountApi;
156        match command {
157            InvoiceCommand::Item { number } => self.inner.invoice(number).report(s),
158            InvoiceCommand::Pdf { number } => self.inner.invoice_pdf(number).report(s),
159            InvoiceCommand::List => self.inner.invoice_list().report(s),
160        }
161    }
162
163    fn execute_product(&mut self, command: &ProductCommand, s: impl Serializer) -> Result<()> {
164        use transip::api::general::GeneralApi;
165        match command {
166            ProductCommand::Elements { name } => self.inner.product_elements(name).report(s),
167            ProductCommand::List => self.inner.products().report(s),
168        }
169    }
170
171    fn execute_vps(&mut self, command: &VpsCommand, s: impl Serializer) -> Result<()> {
172        use transip::api::vps::VpsApi;
173        match command {
174            VpsCommand::Item { name } => self.inner.vps(name).report(s),
175            VpsCommand::Lock { name } => self.inner.vps_set_is_locked(name, true).report(s),
176            VpsCommand::Reset { name } => self.inner.vps_reset(name).report(s),
177            VpsCommand::Start { name } => self.inner.vps_start(name).report(s),
178            VpsCommand::Stop { name } => self.inner.vps_stop(name).report(s),
179            VpsCommand::Unlock { name } => self.inner.vps_set_is_locked(name, false).report(s),
180            VpsCommand::List => self.inner.vps_list().report(s),
181        }
182    }
183
184    pub fn execute(&mut self, command: &SubCommand, s: impl Serializer) -> Result<()> {
185        use transip::api::general::GeneralApi;
186        match command {
187            SubCommand::AvailibilityZones => self.inner.availability_zones().report(s),
188            SubCommand::Comment { text: _ } => Ok(()),
189            SubCommand::Dns(command) => self.execute_dns(command, s),
190            SubCommand::Domain(command) => self.execute_domain(command, s),
191            SubCommand::EmailBox(command) => self.execute_email_box(command, s),
192            SubCommand::EmailForward(command) => self.execute_email_forward(command, s),
193            SubCommand::Invoice(command) => self.execute_invoice(command, s),
194            SubCommand::Onerror { on_error } => {
195                self.onerror = on_error.clone();
196                Ok(())
197            }
198            SubCommand::Ping => self.inner.api_test().report(s),
199            SubCommand::Product(command) => self.execute_product(command, s),
200            SubCommand::Sleep { number_of_seconds } => {
201                std::thread::sleep(Duration::from_secs(*number_of_seconds));
202                Ok(())
203            }
204            SubCommand::Vps(command) => self.execute_vps(command, s),
205            // _ => Ok(()),
206        }
207    }
208}