Skip to content

Commit 16e10e5

Browse files
committed
Migrate oxide_override to its own module
We're about to expand the logic around `OxideOverride`, move it into its own module now for a more understandable diff.
1 parent 2a5dd81 commit 16e10e5

File tree

2 files changed

+226
-218
lines changed

2 files changed

+226
-218
lines changed

cli/src/main.rs

Lines changed: 3 additions & 218 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,12 @@
88
#![cfg_attr(not(test), deny(clippy::print_stdout, clippy::print_stderr))]
99

1010
use std::io;
11-
use std::net::IpAddr;
12-
use std::path::PathBuf;
13-
use std::sync::atomic::AtomicBool;
1411

15-
use anyhow::{Context as _, Result};
12+
use anyhow::Result;
1613
use async_trait::async_trait;
17-
use base64::Engine;
1814
use cli_builder::NewCli;
1915
use context::Context;
20-
use generated_cli::CliConfig;
21-
use oxide::{
22-
types::{
23-
AllowedSourceIps, DerEncodedKeyPair, IdpMetadataSource, IpRange, Ipv4Range, Ipv6Range,
24-
},
25-
Client,
26-
};
16+
use oxide::Client;
2717
use url::Url;
2818

2919
mod cmd_api;
@@ -40,6 +30,7 @@ mod cmd_version;
4030

4131
mod cli_builder;
4232
mod context;
33+
mod oxide_override;
4334
#[macro_use]
4435
mod print;
4536
mod util;
@@ -135,212 +126,6 @@ async fn main() {
135126
}
136127
}
137128

138-
#[derive(Default)]
139-
struct OxideOverride {
140-
needs_comma: AtomicBool,
141-
}
142-
143-
impl OxideOverride {
144-
fn ip_range(matches: &clap::ArgMatches) -> anyhow::Result<IpRange> {
145-
let first = matches.get_one::<IpAddr>("first").unwrap();
146-
let last = matches.get_one::<IpAddr>("last").unwrap();
147-
148-
match (first, last) {
149-
(IpAddr::V4(first), IpAddr::V4(last)) => {
150-
let range = Ipv4Range::try_from(Ipv4Range::builder().first(*first).last(*last))?;
151-
Ok(range.into())
152-
}
153-
(IpAddr::V6(first), IpAddr::V6(last)) => {
154-
let range = Ipv6Range::try_from(Ipv6Range::builder().first(*first).last(*last))?;
155-
Ok(range.into())
156-
}
157-
_ => anyhow::bail!(
158-
"first and last must either both be ipv4 or ipv6 addresses".to_string()
159-
),
160-
}
161-
}
162-
}
163-
164-
impl CliConfig for OxideOverride {
165-
fn success_item<T>(&self, value: &oxide::ResponseValue<T>)
166-
where
167-
T: schemars::JsonSchema + serde::Serialize + std::fmt::Debug,
168-
{
169-
let s = serde_json::to_string_pretty(std::ops::Deref::deref(value))
170-
.expect("failed to serialize return to json");
171-
println_nopipe!("{}", s);
172-
}
173-
174-
fn success_no_item(&self, _: &oxide::ResponseValue<()>) {}
175-
176-
fn error<T>(&self, _value: &oxide::Error<T>)
177-
where
178-
T: schemars::JsonSchema + serde::Serialize + std::fmt::Debug,
179-
{
180-
eprintln_nopipe!("error");
181-
}
182-
183-
fn list_start<T>(&self)
184-
where
185-
T: schemars::JsonSchema + serde::Serialize + std::fmt::Debug,
186-
{
187-
self.needs_comma
188-
.store(false, std::sync::atomic::Ordering::Relaxed);
189-
print_nopipe!("[");
190-
}
191-
192-
fn list_item<T>(&self, value: &T)
193-
where
194-
T: schemars::JsonSchema + serde::Serialize + std::fmt::Debug,
195-
{
196-
let s = serde_json::to_string_pretty(&[value]).expect("failed to serialize result to json");
197-
if self.needs_comma.load(std::sync::atomic::Ordering::Relaxed) {
198-
print_nopipe!(", {}", &s[4..s.len() - 2]);
199-
} else {
200-
print_nopipe!("\n{}", &s[2..s.len() - 2]);
201-
};
202-
self.needs_comma
203-
.store(true, std::sync::atomic::Ordering::Relaxed);
204-
}
205-
206-
fn list_end_success<T>(&self)
207-
where
208-
T: schemars::JsonSchema + serde::Serialize + std::fmt::Debug,
209-
{
210-
if self.needs_comma.load(std::sync::atomic::Ordering::Relaxed) {
211-
println_nopipe!("\n]");
212-
} else {
213-
println_nopipe!("]");
214-
}
215-
}
216-
217-
fn list_end_error<T>(&self, _value: &oxide::Error<T>)
218-
where
219-
T: schemars::JsonSchema + serde::Serialize + std::fmt::Debug,
220-
{
221-
self.list_end_success::<T>()
222-
}
223-
224-
// Deal with all the operations that require an `IpPool` as input
225-
fn execute_ip_pool_range_add(
226-
&self,
227-
matches: &clap::ArgMatches,
228-
request: &mut oxide::builder::IpPoolRangeAdd,
229-
) -> anyhow::Result<()> {
230-
*request = request.to_owned().body(Self::ip_range(matches)?);
231-
Ok(())
232-
}
233-
fn execute_ip_pool_range_remove(
234-
&self,
235-
matches: &clap::ArgMatches,
236-
request: &mut oxide::builder::IpPoolRangeRemove,
237-
) -> anyhow::Result<()> {
238-
*request = request.to_owned().body(Self::ip_range(matches)?);
239-
Ok(())
240-
}
241-
fn execute_ip_pool_service_range_add(
242-
&self,
243-
matches: &clap::ArgMatches,
244-
request: &mut oxide::builder::IpPoolServiceRangeAdd,
245-
) -> anyhow::Result<()> {
246-
*request = request.to_owned().body(Self::ip_range(matches)?);
247-
Ok(())
248-
}
249-
fn execute_ip_pool_service_range_remove(
250-
&self,
251-
matches: &clap::ArgMatches,
252-
request: &mut oxide::builder::IpPoolServiceRangeRemove,
253-
) -> anyhow::Result<()> {
254-
*request = request.to_owned().body(Self::ip_range(matches)?);
255-
Ok(())
256-
}
257-
258-
fn execute_saml_identity_provider_create(
259-
&self,
260-
matches: &clap::ArgMatches,
261-
request: &mut oxide::builder::SamlIdentityProviderCreate,
262-
) -> anyhow::Result<()> {
263-
match matches
264-
.get_one::<clap::Id>("idp_metadata_source")
265-
.map(clap::Id::as_str)
266-
{
267-
Some("metadata-url") => {
268-
let value = matches.get_one::<String>("metadata-url").unwrap();
269-
*request = request.to_owned().body_map(|body| {
270-
body.idp_metadata_source(IdpMetadataSource::Url { url: value.clone() })
271-
});
272-
Ok::<_, anyhow::Error>(())
273-
}
274-
Some("metadata-value") => {
275-
let xml_path = matches.get_one::<PathBuf>("metadata-value").unwrap();
276-
let xml_bytes = std::fs::read(xml_path).with_context(|| {
277-
format!("failed to read metadata XML file {}", xml_path.display())
278-
})?;
279-
let encoded_xml = base64::engine::general_purpose::STANDARD.encode(xml_bytes);
280-
*request = request.to_owned().body_map(|body| {
281-
body.idp_metadata_source(IdpMetadataSource::Base64EncodedXml {
282-
data: encoded_xml,
283-
})
284-
});
285-
Ok(())
286-
}
287-
_ => unreachable!("invalid value for idp_metadata_source group"),
288-
}?;
289-
290-
if matches.get_one::<clap::Id>("signing_keypair").is_some() {
291-
let privkey_path = matches.get_one::<PathBuf>("private-key").unwrap();
292-
let privkey_bytes = std::fs::read(privkey_path).with_context(|| {
293-
format!("failed to read private key file {}", privkey_path.display())
294-
})?;
295-
let encoded_privkey = base64::engine::general_purpose::STANDARD.encode(&privkey_bytes);
296-
297-
let cert_path = matches.get_one::<PathBuf>("public-cert").unwrap();
298-
let cert_bytes = std::fs::read(cert_path).with_context(|| {
299-
format!("failed to read public cert file {}", cert_path.display())
300-
})?;
301-
let encoded_cert = base64::engine::general_purpose::STANDARD.encode(&cert_bytes);
302-
303-
*request = request.to_owned().body_map(|body| {
304-
body.signing_keypair(DerEncodedKeyPair {
305-
private_key: encoded_privkey,
306-
public_cert: encoded_cert,
307-
})
308-
});
309-
}
310-
Ok(())
311-
}
312-
313-
fn execute_networking_allow_list_update(
314-
&self,
315-
matches: &clap::ArgMatches,
316-
request: &mut oxide::builder::NetworkingAllowListUpdate,
317-
) -> anyhow::Result<()> {
318-
match matches
319-
.get_one::<clap::Id>("allow-list")
320-
.map(clap::Id::as_str)
321-
{
322-
Some("any") => {
323-
let value = matches.get_one::<bool>("any").unwrap();
324-
assert!(value);
325-
*request = request
326-
.to_owned()
327-
.body_map(|body| body.allowed_ips(AllowedSourceIps::Any));
328-
}
329-
Some("ips") => {
330-
let values: Vec<IpOrNet> = matches.get_many("ips").unwrap().cloned().collect();
331-
*request = request.to_owned().body_map(|body| {
332-
body.allowed_ips(AllowedSourceIps::List(
333-
values.into_iter().map(IpOrNet::into_ip_net).collect(),
334-
))
335-
});
336-
}
337-
_ => unreachable!("invalid value for allow-list group"),
338-
}
339-
340-
Ok(())
341-
}
342-
}
343-
344129
#[cfg(test)]
345130
mod tests {
346131
use clap::Command;

0 commit comments

Comments
 (0)