Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ pub async fn exec_subcommand(
"delete" => delete::exec(config, args).await,
"logs" => logs::exec(config, args).await,
"sql" => sql::exec(config, args).await,
"dns" => dns::exec(config, args).await,
"rename" => dns::exec(config, args).await,
"generate" => generate::exec(config, args).await,
"list" => list::exec(config, args).await,
"init" => init::exec(config, args).await,
Expand Down
147 changes: 22 additions & 125 deletions crates/cli/src/subcommands/dns.rs
Original file line number Diff line number Diff line change
@@ -1,97 +1,38 @@
use crate::common_args;
use crate::config::Config;
use crate::util::{
add_auth_header_opt, decode_identity, get_auth_header, spacetime_dns, spacetime_register_tld, spacetime_reverse_dns,
};
use crate::util::{add_auth_header_opt, decode_identity, get_auth_header, spacetime_register_tld};
use clap::ArgMatches;
use clap::{Arg, Command};
use reqwest::Url;

use spacetimedb_client_api_messages::name::{DnsLookupResponse, InsertDomainResult, RegisterTldResult};
use spacetimedb_client_api_messages::name::{InsertDomainResult, RegisterTldResult};

pub fn cli() -> Command {
Command::new("dns")
.args_conflicts_with_subcommands(true)
.subcommand_required(true)
.subcommands(get_subcommands())
.about("Create, manage and query domains")
Command::new("rename")
.about("Rename a database")
.arg(
Arg::new("new-name")
.long("to")
.required(true)
.help("The new name you would like to assign"),
)
.arg(
Arg::new("database-identity")
.required(true)
.help("The database identity to rename"),
)
.arg(common_args::server().help("The nickname, host name or URL of the server on which to set the name"))
.after_help("Run `spacetime rename --help` for more detailed information.\n")
}

pub async fn exec(config: Config, args: &ArgMatches) -> Result<(), anyhow::Error> {
let (cmd, subcommand_args) = args.subcommand().expect("Subcommand required");
exec_subcommand(config, cmd, subcommand_args).await
}

fn get_subcommands() -> Vec<Command> {
vec![
Command::new("register-tld")
.about("Registers a new top level domain")
.arg(
Arg::new("tld")
.required(true)
.help("The top level domain that you would like to register"),
)
.arg(
common_args::server()
.help("The nickname, host name or URL of the server on which to register the domain"),
)
.after_help("Run `spacetime dns register-tld --help` for more detailed information.\n"),
Command::new("lookup")
.about("Resolves a domain to a database identity")
.arg(
Arg::new("domain")
.required(true)
.help("The name of the domain to lookup"),
)
.arg(
common_args::server()
.help("The nickname, host name or URL of the server on which to look up the domain name"),
)
.after_help("Run `spacetime dns lookup --help` for more detailed information"),
Command::new("reverse-lookup")
.about("Returns the domains for the provided database identity")
.arg(
Arg::new("database-identity")
.required(true)
.help("The database identity you would like to find all of the known domains for"),
)
.arg(
common_args::server()
.help("The nickname, host name or URL of the server on which to look up the database identity"),
)
.after_help("Run `spacetime dns reverse-lookup --help` for more detailed information.\n"),
Command::new("set-name")
.about("Sets the domain of the database")
.arg(
Arg::new("domain")
.required(true)
.help("The domain you would like to assign or create"),
)
.arg(
Arg::new("database-identity")
.required(true)
.help("The database identity to assign to the domain"),
)
.arg(common_args::server().help("The nickname, host name or URL of the server on which to set the name"))
.after_help("Run `spacetime dns set-name --help` for more detailed information.\n"),
]
}

async fn exec_subcommand(config: Config, cmd: &str, args: &ArgMatches) -> Result<(), anyhow::Error> {
match cmd {
"register-tld" => exec_register_tld(config, args).await,
"lookup" => exec_dns_lookup(config, args).await,
"reverse-lookup" => exec_reverse_dns(config, args).await,
"set-name" => exec_set_name(config, args).await,
unknown => Err(anyhow::anyhow!("Invalid subcommand: {}", unknown)),
}
}

async fn exec_register_tld(mut config: Config, args: &ArgMatches) -> Result<(), anyhow::Error> {
let tld = args.get_one::<String>("tld").unwrap().clone();
let domain = args.get_one::<String>("new-name").unwrap();
let database_identity = args.get_one::<String>("database-identity").unwrap();
let server = args.get_one::<String>("server").map(|s| s.as_ref());
let identity = decode_identity(&config)?;
let auth_header = get_auth_header(&config, false)?;

match spacetime_register_tld(&mut config, &tld, server).await? {
match spacetime_register_tld(&config, domain, server).await? {
RegisterTldResult::Success { domain } => {
println!("Registered domain: {}", domain);
}
Expand All @@ -102,50 +43,6 @@ async fn exec_register_tld(mut config: Config, args: &ArgMatches) -> Result<(),
println!("Domain is already registered by the identity you provided: {}", domain);
}
}
config.save();

Ok(())
}

pub async fn exec_dns_lookup(config: Config, args: &ArgMatches) -> Result<(), anyhow::Error> {
let domain = args.get_one::<String>("domain").unwrap();
let server = args.get_one::<String>("server").map(|s| s.as_ref());

let response = spacetime_dns(&config, domain, server).await?;
match response {
DnsLookupResponse::Success { domain: _, identity } => {
println!("{}", identity);
}
DnsLookupResponse::Failure { domain } => {
println!("No such database: {}", domain);
}
}
Ok(())
}

pub async fn exec_reverse_dns(config: Config, args: &ArgMatches) -> Result<(), anyhow::Error> {
let database_identity = args.get_one::<String>("database-identity").unwrap();
let server = args.get_one::<String>("server").map(|s| s.as_ref());
let response = spacetime_reverse_dns(&config, database_identity, server).await?;
if response.names.is_empty() {
Err(anyhow::anyhow!(
"Could not find a name for the identity: {}",
database_identity
))
} else {
for name in response.names {
println!("{}", name);
}
Ok(())
}
}

pub async fn exec_set_name(config: Config, args: &ArgMatches) -> Result<(), anyhow::Error> {
let domain = args.get_one::<String>("domain").unwrap();
let database_identity = args.get_one::<String>("database-identity").unwrap();
let server = args.get_one::<String>("server").map(|s| s.as_ref());
let identity = decode_identity(&config)?;
let auth_header = get_auth_header(&config, false)?;

let builder = reqwest::Client::new().get(Url::parse_with_params(
format!("{}/database/set_name", config.get_host_url(server)?).as_str(),
Expand Down
4 changes: 1 addition & 3 deletions crates/cli/src/subcommands/publish.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,9 +193,7 @@ pub async fn exec(config: Config, args: &ArgMatches) -> Result<(), anyhow::Error
PublishResult::TldNotRegistered { domain } => {
return Err(anyhow::anyhow!(
"The top level domain that you provided is not registered.\n\
This tld is not yet registered to any identity. You can register this domain with the following command:\n\
\n\
\tspacetime dns register-tld {}\n",
This tld is not yet registered to any identity: {}",
domain.tld()
));
}
Expand Down
2 changes: 1 addition & 1 deletion crates/cli/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ pub async fn spacetime_dns(
/// identity will be looked up in the config and it will be used instead. Returns Ok() if the
/// domain is successfully registered, returns Err otherwise.
pub async fn spacetime_register_tld(
config: &mut Config,
config: &Config,
tld: &str,
server: Option<&str>,
) -> Result<RegisterTldResult, anyhow::Error> {
Expand Down
63 changes: 31 additions & 32 deletions smoketests/tests/domains.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,47 +3,46 @@
class Domains(Smoketest):
AUTOPUBLISH = False

def test_register_domain(self):
"""Attempts to register some valid domains and makes sure invalid domains cannot be registered"""

rand_domain = random_string()
def test_set_name(self):
"""Tests the functionality of the set-name command"""

self.new_identity()
self.spacetime("dns", "register-tld", rand_domain)
self.publish_module()

self.publish_module(rand_domain)
self.publish_module(f"{rand_domain}/test")
self.publish_module(f"{rand_domain}/test/test2")
rand_name = random_string()

# This should throw an exception before there's a db with this name
with self.assertRaises(Exception):
self.publish_module(f"{rand_domain}//test")
with self.assertRaises(Exception):
self.publish_module(f"{rand_domain}/test/")
with self.assertRaises(Exception):
self.publish_module(f"{rand_domain}/test//test2")

def test_reverse_dns(self):
"""This tests the functionality of spacetime reverse dns lookups"""
self.spacetime("logs", rand_name)

rand_domain = random_string()
self.spacetime("dns", "register-tld", rand_domain)
self.spacetime("rename", "--to", rand_name, self.database_identity)

self.publish_module(rand_domain)
# Now we're essentially just testing that it *doesn't* throw an exception
self.spacetime("logs", rand_name)

names = self.spacetime("dns", "reverse-lookup", self.resolved_identity).splitlines()
self.assertIn(rand_domain, names)
def test_subdomain_behavior(self):
"""Test how we treat the / character in published names"""

def test_set_name(self):
"""Tests the functionality of the set-name command"""
root_name = random_string()
self.publish_module(root_name)
id_to_rename = self.database_identity

self.publish_module()
self.publish_module(f"{root_name}/test")

rand_name = random_string()
with self.assertRaises(Exception):
self.publish_module(f"{root_name}//test")

with self.assertRaises(Exception):
self.publish_module(f"{root_name}/test/")

self.spacetime("dns", "register-tld", rand_name)
self.spacetime("dns", "set-name", rand_name, self.database_identity)
lookup_result = self.spacetime("dns", "lookup", rand_name).strip()
self.assertEqual(lookup_result, self.database_identity)
def test_set_to_existing_name(self):
"""Test that we can't rename to a name already in use"""

names = self.spacetime("dns", "reverse-lookup", self.database_identity).splitlines()
self.assertIn(rand_name, names)
self.publish_module()
id_to_rename = self.database_identity

rename_to = random_string()
self.publish_module(rename_to)

# This should throw an exception because there's a db with this name
with self.assertRaises(Exception):
self.spacetime("rename", "--to", rename_to, id_to_rename)
Loading