From 3ab06a07ec008c0abef9dde96c448c72029e6a57 Mon Sep 17 00:00:00 2001 From: rzmk <30333942+rzmk@users.noreply.github.com> Date: Wed, 3 Sep 2025 13:17:07 -0400 Subject: [PATCH] feat: add improved interactivity, config customizability, disable DRUF --- README.md | 6 +- src/main.rs | 450 ++++++++++++++++++++++++++++------------------- src/questions.rs | 64 +++++++ src/steps.rs | 19 ++ 4 files changed, 349 insertions(+), 190 deletions(-) create mode 100644 src/questions.rs create mode 100644 src/steps.rs diff --git a/README.md b/README.md index 929777d..7085810 100644 --- a/README.md +++ b/README.md @@ -5,12 +5,8 @@ - [DataStore extension](https://docs.ckan.org/en/2.11/maintaining/datastore.html) - [ckanext-scheming extension](https://github.com/ckan/ckanext-scheming) - [DataPusher+ extension](https://github.com/dathere/datapusher-plus) -- [DRUF mode](https://github.com/dathere/datapusher-plus?tab=readme-ov-file#druf-dataset-resource-upload-first-workflow) -The [`datatablesview-plus` extension](https://github.com/dathere/ckanext-datatables-plus) is planned to be included in a future release. - -> [!NOTE] -> We plan on including customizability for enabling/disabling features in a future release. +[DRUF mode](https://github.com/dathere/datapusher-plus?tab=readme-ov-file#druf-dataset-resource-upload-first-workflow) is available but disabled by default. The [`datatablesview-plus` extension](https://github.com/dathere/ckanext-datatables-plus) is planned to be included in a future release. ## Quick start diff --git a/src/main.rs b/src/main.rs index f0ecb33..6115724 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,11 @@ +mod questions; +mod steps; mod styles; -use crate::styles::{highlighted_text, important_text, step_text, success_text}; +use crate::{ + questions::{question_ckan_version, question_ssh, question_sysadmin}, + styles::{highlighted_text, important_text, step_text, success_text}, +}; use anyhow::Result; use clap::Parser; use human_panic::{metadata, setup_panic}; @@ -19,6 +24,22 @@ struct Args { default: bool, } +struct Sysadmin { + username: String, + password: String, + email: String, +} + +struct Config { + ssh: bool, + ckan_version: String, + sysadmin: Sysadmin, + extension_datastore: bool, + extension_ckanext_scheming: bool, + extension_datapusher_plus: bool, + druf_mode: bool, +} + fn main() -> Result<()> { setup_panic!(metadata!() .homepage("https://dathere.com") @@ -26,33 +47,85 @@ fn main() -> Result<()> { let args = Args::parse(); - println!("Welcome to the ckan-devstaller!"); - println!( - "ckan-devstaller is provided by datHere - {}\n", - highlighted_text("https://datHere.com"), - ); - println!( - "This installer should assist in setting up {} from a source installation along with ckan-compose (https://github.com/tino097/ckan-compose). If you have any issues, please report them at https://github.com/dathere/ckan-devstaller/issues.", - highlighted_text("CKAN 2.11.3") - ); - println!( - "{}", - important_text( - "This installer is only intended for a brand new installation of Ubuntu 22.04." - ) - ); + // Set up default config + let sh = Shell::new()?; + let username = cmd!(sh, "whoami").read()?; + steps::step_intro(); - let ans = if args.default { - true + let default_config_text = r#" + The default configuration for ckan-devstaller does the following: + - Install openssh-server to enable SSH access + - Install ckan-compose (https://github.com/tino097/ckan-compose) which sets up the CKAN backend (PostgreSQL, SOLR, Redis) + - Install CKAN v2.11.3 + - Install the DataStore extension + - Install the ckanext-scheming extension + - Install the DataPusher+ extension + - Disable DRUF mode for DataPusher+ +"#; + println!("{default_config_text}"); + let answer_customize = if args.default { + false } else { - Confirm::new("Would you like to begin the installation?") - .with_default(false) - .prompt()? + Confirm::new( + "Would you like to customize any of these features for your CKAN installation?", + ) + .prompt()? + }; + let default_sysadmin = Sysadmin { + username: username.clone(), + password: "password".to_string(), + email: format!("{username}@localhost"), + }; + let config = if answer_customize { + let answer_ssh = question_ssh()?; + let answer_ckan_version = question_ckan_version()?; + let answer_sysadmin = question_sysadmin(username.clone())?; + // let answer_extension_datastore = Confirm::new("Would you like to install the DataStore extension?") + // .with_default(true) + // .prompt()?; + // let answer_extension_ckanext_scheming = Confirm::new("Would you like to install the ckanext-scheming extension?") + // .with_default(true) + // .prompt()?; + let answer_extension_datapusher_plus = + Confirm::new("Would you like to install the DataPusher+ extension?") + .with_default(true) + .prompt()?; + let answer_druf_mode = if answer_extension_datapusher_plus { + Confirm::new("Would you like to enable DRUF mode for DataPusher+?") + .with_default(false) + .prompt()? + } else { + false + }; + Config { + ssh: answer_ssh, + ckan_version: answer_ckan_version, + sysadmin: answer_sysadmin, + extension_datastore: true, + extension_ckanext_scheming: true, + extension_datapusher_plus: answer_extension_datapusher_plus, + druf_mode: answer_druf_mode, + } + } else { + Config { + ssh: true, + ckan_version: "2.11.3".to_string(), + sysadmin: default_sysadmin, + extension_datastore: true, + extension_ckanext_scheming: true, + extension_datapusher_plus: true, + druf_mode: false, + } }; - if ans { - let sh = Shell::new()?; - let username = cmd!(sh, "whoami").read()?; + let begin_installation = if args.default { + true + } else { + Confirm::new("Would you like to begin the installation?").prompt()? + }; + + if begin_installation { + println!("{}", important_text("Starting installation...")); println!( "\n{} Running {} and {}...", step_text("1."), @@ -71,11 +144,20 @@ fn main() -> Result<()> { success_text("✅ 1. Successfully ran update and upgrade commands.") ); - println!("\n{} Installing curl and enabling SSH...", step_text("2.")); - cmd!(sh, "sudo apt install curl openssh-server -y").run()?; + println!( + "\n{} Installing {}...", + step_text("2."), + highlighted_text("curl") + ); + cmd!(sh, "sudo apt install curl -y").run()?; + println!("{}", success_text("✅ 2.1. Successfully installed curl.")); + if config.ssh { + println!("\n{} Installing openssh-server...", step_text("2.")); + cmd!(sh, "sudo apt install openssh-server -y").run()?; + } println!( "{}", - success_text("✅ 2. Successfully installed curl and enabled SSH.") + success_text("✅ 2.2. Successfully installed openssh-server.") ); let dpkg_l_output = cmd!(sh, "dpkg -l").read()?; @@ -129,7 +211,11 @@ POSTGRES_PASSWORD=pass"; cmd!(sh, "sudo ../ahoy up").run()?; println!("{}", success_text("✅ 5. Successfully ran ckan-compose.")); - println!("\n{} Installing CKAN 2.11.3...", step_text("6."),); + println!( + "\n{} Installing CKAN {}...", + step_text("6."), + config.ckan_version + ); cmd!(sh, "sudo apt install python3-dev libpq-dev python3-pip python3-venv git-core redis-server -y").run()?; cmd!(sh, "sudo mkdir -p /usr/lib/ckan/default").run()?; cmd!(sh, "sudo chown {username} /usr/lib/ckan/default").run()?; @@ -137,7 +223,11 @@ POSTGRES_PASSWORD=pass"; let venv = VirtualEnv::with_path(&sh, &venv_path)?; venv.pip_upgrade("pip")?; venv.pip_install( - "git+https://github.com/ckan/ckan.git@ckan-2.11.3#egg=ckan[requirements]", + format!( + "git+https://github.com/ckan/ckan.git@ckan-{}#egg=ckan[requirements]", + config.ckan_version + ) + .as_str(), )?; cmd!(sh, "sudo mkdir -p /etc/ckan/default").run()?; cmd!(sh, "sudo chown -R {username} /etc/ckan/").run()?; @@ -159,118 +249,124 @@ POSTGRES_PASSWORD=pass"; cmd!(sh, "sudo mkdir -p ckan/default").run()?; cmd!(sh, "sudo chown {username}.{username} ckan/default").run()?; cmd!(sh, "ckan -c /etc/ckan/default/ckan.ini db init").run()?; - cmd!(sh, "ckan -c /etc/ckan/default/ckan.ini user add {username} password=password email={username}@localhost").run()?; + let sysadmin_username = config.sysadmin.username; + let sysadmin_password = config.sysadmin.password; + let sysadmin_email = config.sysadmin.email; + cmd!(sh, "ckan -c /etc/ckan/default/ckan.ini user add {sysadmin_username} password={sysadmin_password} email={sysadmin_email}").run()?; cmd!( sh, - "ckan -c /etc/ckan/default/ckan.ini sysadmin add {username}" + "ckan -c /etc/ckan/default/ckan.ini sysadmin add {sysadmin_username}" ) .run()?; - println!("{}", success_text("✅ 6. Installed CKAN 2.11.3.")); - - println!( - "\n{} Enabling DataStore plugin, adding config URLs in /etc/ckan/default/ckan.ini and updating permissions...", - step_text("7."), - ); - // TODO: use the ckan config-tool command instead of rust-ini - let mut conf = ini::Ini::load_from_file("/etc/ckan/default/ckan.ini")?; - let app_main_section = conf.section_mut(Some("app:main")).unwrap(); - let mut ckan_plugins = app_main_section.get("ckan.plugins").unwrap().to_string(); - ckan_plugins.push_str(" datastore"); - app_main_section.insert("ckan.plugins", ckan_plugins); - app_main_section.insert( - "ckan.datastore.write_url", - "postgresql://ckan_default:pass@localhost/datastore_default", - ); - app_main_section.insert( - "ckan.datastore.read_url", - "postgresql://datastore_default:pass@localhost/datastore_default", - ); - app_main_section.insert("ckan.datastore.sqlsearch.enabled", "true"); - conf.write_to_file("/etc/ckan/default/ckan.ini")?; - let postgres_container_id = cmd!( - sh, - "sudo docker ps -aqf name=^ckan-devstaller-project-postgres$" - ) - .read()?; - let set_permissions_output = cmd!( - sh, - "ckan -c /etc/ckan/default/ckan.ini datastore set-permissions" - ) - .read()?; - std::fs::write("permissions.sql", set_permissions_output)?; - loop { - std::thread::sleep(std::time::Duration::from_secs(2)); - if std::fs::exists("permissions.sql")? { - break; - } - } - sh.change_dir(format!("/home/{username}")); - cmd!( - sh, - "sudo docker cp permissions.sql {postgres_container_id}:/permissions.sql" - ) - .run()?; - cmd!(sh, "sudo docker exec {postgres_container_id} psql -U ckan_default --set ON_ERROR_STOP=1 -f permissions.sql").run()?; println!( "{}", - success_text( - "✅ 7. Enabled DataStore plugin, set DataStore URLs in /etc/ckan/default/ckan.ini, and updated permissions." + success_text(format!("✅ 6. Installed CKAN {}.", config.ckan_version).as_str()) + ); + + if config.extension_datapusher_plus { + println!( + "\n{} Enabling DataStore plugin, adding config URLs in /etc/ckan/default/ckan.ini and updating permissions...", + step_text("7."), + ); + let mut conf = ini::Ini::load_from_file("/etc/ckan/default/ckan.ini")?; + let app_main_section = conf.section_mut(Some("app:main")).unwrap(); + let mut ckan_plugins = app_main_section.get("ckan.plugins").unwrap().to_string(); + ckan_plugins.push_str(" datastore"); + app_main_section.insert("ckan.plugins", ckan_plugins); + app_main_section.insert( + "ckan.datastore.write_url", + "postgresql://ckan_default:pass@localhost/datastore_default", + ); + app_main_section.insert( + "ckan.datastore.read_url", + "postgresql://datastore_default:pass@localhost/datastore_default", + ); + app_main_section.insert("ckan.datastore.sqlsearch.enabled", "true"); + conf.write_to_file("/etc/ckan/default/ckan.ini")?; + let postgres_container_id = cmd!( + sh, + "sudo docker ps -aqf name=^ckan-devstaller-project-postgres$" ) - ); + .read()?; + let set_permissions_output = cmd!( + sh, + "ckan -c /etc/ckan/default/ckan.ini datastore set-permissions" + ) + .read()?; + std::fs::write("permissions.sql", set_permissions_output)?; + loop { + std::thread::sleep(std::time::Duration::from_secs(2)); + if std::fs::exists("permissions.sql")? { + break; + } + } + sh.change_dir(format!("/home/{username}")); + cmd!( + sh, + "sudo docker cp permissions.sql {postgres_container_id}:/permissions.sql" + ) + .run()?; + cmd!(sh, "sudo docker exec {postgres_container_id} psql -U ckan_default --set ON_ERROR_STOP=1 -f permissions.sql").run()?; + println!( + "{}", + success_text( + "✅ 7. Enabled DataStore plugin, set DataStore URLs in /etc/ckan/default/ckan.ini, and updated permissions." + ) + ); - println!( - "{}", - step_text("\n{} Installing ckanext-scheming and DataPusher+ extensions..."), - ); - cmd!( + println!( + "{}", + step_text("\n{} Installing ckanext-scheming and DataPusher+ extensions..."), + ); + cmd!( sh, "pip install -e git+https://github.com/ckan/ckanext-scheming.git#egg=ckanext-scheming" ) .run()?; - let mut conf = ini::Ini::load_from_file("/etc/ckan/default/ckan.ini")?; - let app_main_section = conf.section_mut(Some("app:main")).unwrap(); - let mut ckan_plugins = app_main_section.get("ckan.plugins").unwrap().to_string(); - ckan_plugins.push_str(" scheming_datasets"); - cmd!( + let mut conf = ini::Ini::load_from_file("/etc/ckan/default/ckan.ini")?; + let app_main_section = conf.section_mut(Some("app:main")).unwrap(); + let mut ckan_plugins = app_main_section.get("ckan.plugins").unwrap().to_string(); + ckan_plugins.push_str(" scheming_datasets"); + cmd!( sh, "ckan config-tool /etc/ckan/default/ckan.ini -s app:main ckan.plugins={ckan_plugins}" ) .run()?; - cmd!(sh, "ckan config-tool /etc/ckan/default/ckan.ini -s app:main scheming.presets=ckanext.scheming:presets.json").run()?; - cmd!(sh, "ckan config-tool /etc/ckan/default/ckan.ini -s app:main scheming.dataset_fallback=false").run()?; - // app_main_section.insert("ckan.plugins", ckan_plugins); - // app_main_section.insert("scheming.presets", "ckanext.scheming:presets.json"); - // app_main_section.insert("scheming.dataset_fallback", "false"); - // conf.write_to_file("/etc/ckan/default/ckan.ini")?; - // Install DataPusher+ - cmd!(sh, "sudo apt install python3-virtualenv python3-dev python3-pip python3-wheel build-essential libxslt1-dev libxml2-dev zlib1g-dev git libffi-dev libpq-dev uchardet -y").run()?; - sh.change_dir("/usr/lib/ckan/default/src"); - cmd!(sh, "pip install -e git+https://github.com/dathere/datapusher-plus.git@main#egg=datapusher-plus").run()?; - sh.change_dir("/usr/lib/ckan/default/src/datapusher-plus"); - cmd!(sh, "pip install -r requirements.txt").run()?; - sh.change_dir(format!("/home/{username}")); - cmd!(sh, "wget https://github.com/dathere/qsv/releases/download/4.0.0/qsv-4.0.0-x86_64-unknown-linux-gnu.zip").run()?; - cmd!(sh, "sudo apt install unzip -y").run()?; - cmd!(sh, "unzip qsv-4.0.0-x86_64-unknown-linux-gnu.zip").run()?; - cmd!(sh, "sudo rm -rf qsv-4.0.0-x86_64-unknown-linux-gnu.zip").run()?; - cmd!(sh, "sudo mv ./qsvdp_glibc-2.31 /usr/local/bin/qsvdp").run()?; - let mut conf = ini::Ini::load_from_file("/etc/ckan/default/ckan.ini")?; - let app_main_section = conf.section_mut(Some("app:main")).unwrap(); - let mut ckan_plugins = app_main_section.get("ckan.plugins").unwrap().to_string(); - ckan_plugins.push_str(" datapusher_plus"); - cmd!( + cmd!(sh, "ckan config-tool /etc/ckan/default/ckan.ini -s app:main scheming.presets=ckanext.scheming:presets.json").run()?; + cmd!(sh, "ckan config-tool /etc/ckan/default/ckan.ini -s app:main scheming.dataset_fallback=false").run()?; + // app_main_section.insert("ckan.plugins", ckan_plugins); + // app_main_section.insert("scheming.presets", "ckanext.scheming:presets.json"); + // app_main_section.insert("scheming.dataset_fallback", "false"); + // conf.write_to_file("/etc/ckan/default/ckan.ini")?; + // Install DataPusher+ + cmd!(sh, "sudo apt install python3-virtualenv python3-dev python3-pip python3-wheel build-essential libxslt1-dev libxml2-dev zlib1g-dev git libffi-dev libpq-dev uchardet -y").run()?; + sh.change_dir("/usr/lib/ckan/default/src"); + cmd!(sh, "pip install -e git+https://github.com/dathere/datapusher-plus.git@main#egg=datapusher-plus").run()?; + sh.change_dir("/usr/lib/ckan/default/src/datapusher-plus"); + cmd!(sh, "pip install -r requirements.txt").run()?; + sh.change_dir(format!("/home/{username}")); + cmd!(sh, "wget https://github.com/dathere/qsv/releases/download/4.0.0/qsv-4.0.0-x86_64-unknown-linux-gnu.zip").run()?; + cmd!(sh, "sudo apt install unzip -y").run()?; + cmd!(sh, "unzip qsv-4.0.0-x86_64-unknown-linux-gnu.zip").run()?; + cmd!(sh, "sudo rm -rf qsv-4.0.0-x86_64-unknown-linux-gnu.zip").run()?; + cmd!(sh, "sudo mv ./qsvdp_glibc-2.31 /usr/local/bin/qsvdp").run()?; + let mut conf = ini::Ini::load_from_file("/etc/ckan/default/ckan.ini")?; + let app_main_section = conf.section_mut(Some("app:main")).unwrap(); + let mut ckan_plugins = app_main_section.get("ckan.plugins").unwrap().to_string(); + ckan_plugins.push_str(" datapusher_plus"); + cmd!( sh, "ckan config-tool /etc/ckan/default/ckan.ini -s app:main ckan.plugins={ckan_plugins}" ) .run()?; - cmd!(sh, "ckan config-tool /etc/ckan/default/ckan.ini -s app:main scheming.dataset_schemas=ckanext.datapusher_plus:dataset-druf.yaml").run()?; - // app_main_section.insert("ckan.plugins", ckan_plugins); - // app_main_section.insert( - // "scheming.dataset_schemas", - // "ckanext.datapusher_plus:dataset-druf.yaml", - // ); - // conf.write_to_file("/etc/ckan/default/ckan.ini")?; - let dpp_default_config = r#" + cmd!(sh, "ckan config-tool /etc/ckan/default/ckan.ini -s app:main scheming.dataset_schemas=ckanext.datapusher_plus:dataset-druf.yaml").run()?; + // app_main_section.insert("ckan.plugins", ckan_plugins); + // app_main_section.insert( + // "scheming.dataset_schemas", + // "ckanext.datapusher_plus:dataset-druf.yaml", + // ); + // conf.write_to_file("/etc/ckan/default/ckan.ini")?; + let dpp_default_config = r#" ckanext.datapusher_plus.use_proxy = false ckanext.datapusher_plus.download_proxy = ckanext.datapusher_plus.ssl_verify = false @@ -316,75 +412,59 @@ ckanext.datapusher_plus.auto_unzip_one_file = true ckanext.datapusher_plus.api_token = ckanext.datapusher_plus.describeGPT_api_key = ckanext.datapusher_plus.file_bin = /usr/bin/file -ckanext.datapusher_plus.enable_druf = true +ckanext.datapusher_plus.enable_druf = false ckanext.datapusher_plus.enable_form_redirect = true "#; - std::fs::write("dpp_default_config.ini", dpp_default_config)?; - cmd!( - sh, - "ckan config-tool /etc/ckan/default/ckan.ini -f dpp_default_config.ini" - ) - .run()?; - let resource_formats_str = - std::fs::read_to_string("/usr/lib/ckan/default/src/ckan/config/resource_formats.json")?; - let mut resource_formats_val: serde_json::Value = - serde_json::from_str(&resource_formats_str)?; - let all_resource_formats = resource_formats_val - .get_mut(0) - .unwrap() - .as_array_mut() - .unwrap(); - all_resource_formats.push(json!([ - "TAB", - "Tab Separated Values File", - "text/tab-separated-values", - [] - ])); - std::fs::write( - "/usr/lib/ckan/default/src/ckan/config/resource_formats.json", - serde_json::to_string(&resource_formats_val)?, - )?; - cmd!(sh, "sudo locale-gen en_US.UTF-8").run()?; - cmd!(sh, "sudo update-locale").run()?; - let token_command_output = cmd!( - sh, - "ckan -c /etc/ckan/default/ckan.ini user token add {username} dpplus" - ) - .read()?; - let tail_output = cmd!(sh, "tail -n 1").stdin(token_command_output).read()?; - let dpp_api_token = cmd!(sh, "tr -d '\t'").stdin(tail_output).read()?; - cmd!(sh, "ckan config-tool /etc/ckan/default/ckan.ini ckanext.datapusher_plus.api_token={dpp_api_token}").env("LC_ALL", "en_US.UTF-8").run()?; - cmd!( - sh, - "ckan -c /etc/ckan/default/ckan.ini db upgrade -p datapusher_plus" - ) - .run()?; - println!( - "{}", - success_text("✅ 8. Installed ckanext-scheming and DataPusher+ extensions.") - ); + std::fs::write("dpp_default_config.ini", dpp_default_config)?; + cmd!( + sh, + "ckan config-tool /etc/ckan/default/ckan.ini -f dpp_default_config.ini" + ) + .run()?; + let resource_formats_str = std::fs::read_to_string( + "/usr/lib/ckan/default/src/ckan/config/resource_formats.json", + )?; + let mut resource_formats_val: serde_json::Value = + serde_json::from_str(&resource_formats_str)?; + let all_resource_formats = resource_formats_val + .get_mut(0) + .unwrap() + .as_array_mut() + .unwrap(); + all_resource_formats.push(json!([ + "TAB", + "Tab Separated Values File", + "text/tab-separated-values", + [] + ])); + std::fs::write( + "/usr/lib/ckan/default/src/ckan/config/resource_formats.json", + serde_json::to_string(&resource_formats_val)?, + )?; + cmd!(sh, "sudo locale-gen en_US.UTF-8").run()?; + cmd!(sh, "sudo update-locale").run()?; + let token_command_output = cmd!( + sh, + "ckan -c /etc/ckan/default/ckan.ini user token add {sysadmin_username} dpplus" + ) + .read()?; + let tail_output = cmd!(sh, "tail -n 1").stdin(token_command_output).read()?; + let dpp_api_token = cmd!(sh, "tr -d '\t'").stdin(tail_output).read()?; + cmd!(sh, "ckan config-tool /etc/ckan/default/ckan.ini ckanext.datapusher_plus.api_token={dpp_api_token}").env("LC_ALL", "en_US.UTF-8").run()?; + cmd!( + sh, + "ckan -c /etc/ckan/default/ckan.ini db upgrade -p datapusher_plus" + ) + .run()?; + println!( + "{}", + success_text("✅ 8. Installed ckanext-scheming and DataPusher+ extensions.") + ); + } - println!("\n{}", success_text("✅ 9. Running CKAN instance...")); + println!("\n{}", success_text("✅ Running CKAN instance...")); cmd!(sh, "ckan -c /etc/ckan/default/ckan.ini run").run()?; } Ok(()) } - -struct Config { - ssh: bool, -} - -fn get_config_from_prompts() -> Result { - let ssh = Confirm::new("Would you like to enable SSH? (optional)") - .with_default(false) - .with_help_message( - format!( - "This step would install {}", - highlighted_text("openssh-server") - ) - .as_str(), - ) - .prompt()?; - Ok(Config { ssh }) -} diff --git a/src/questions.rs b/src/questions.rs new file mode 100644 index 0000000..f8d5122 --- /dev/null +++ b/src/questions.rs @@ -0,0 +1,64 @@ +use crate::{Sysadmin, styles::highlighted_text}; +use anyhow::Result; +use inquire::{Confirm, Select, Text}; + +pub fn question_ssh() -> Result { + Ok(Confirm::new("Would you like to enable SSH? (optional)") + .with_default(false) + .with_help_message( + format!( + "This step would install {}", + highlighted_text("openssh-server") + ) + .as_str(), + ) + .prompt()?) +} + +pub fn question_ckan_version() -> Result { + let ckan_version_options: Vec<&str> = vec!["2.11.3", "2.10.8", "Other"]; + let answer_ckan_version = Select::new( + "What CKAN version would you like to install? (optional)", + ckan_version_options, + ) + .with_help_message("We recommend using the latest compatible version of CKAN. Please do not choose 'Other' option unless for testing purposes as the CKAN version may not be supported and may cause a broken installation.") + .prompt()?; + if answer_ckan_version == "Other" { + Ok( + Text::new("What CKAN version would you like to install? (optional)") + .with_default("2.11.3") + .prompt()?, + ) + } else { + Ok(answer_ckan_version.to_string()) + } +} + +pub fn question_sysadmin(username: String) -> Result { + let configure_sysadmin = Confirm::new("Would you like to configure the sysadmin account for your CKAN instance?") + .with_help_message(format!("The following values are set as defaults for the sysadmin account:\n\n- Username: {username}\n- Password: password\n- Email: {username}@localhost\n").as_str()) + .prompt()?; + if configure_sysadmin { + let username = Text::new("What should your sysadmin username be set to?") + .with_default(username.clone().as_str()) + .prompt()?; + let password = Text::new("What should your sysadmin password be set to?") + .with_default("password") + .with_help_message("The password must be at least 8 characters long") + .prompt()?; + let email = Text::new("What should your sysadmin email be set to?") + .with_default(format!("{username}@localhost").as_str()) + .prompt()?; + Ok(Sysadmin { + username, + password, + email, + }) + } else { + Ok(Sysadmin { + username: username.clone(), + password: "password".to_string(), + email: format!("{username}@localhost"), + }) + } +} diff --git a/src/steps.rs b/src/steps.rs new file mode 100644 index 0000000..d06981c --- /dev/null +++ b/src/steps.rs @@ -0,0 +1,19 @@ +use crate::styles::{highlighted_text, important_text}; + +pub fn step_intro() { + println!("Welcome to the ckan-devstaller!"); + println!( + "ckan-devstaller is provided by datHere - {}\n", + highlighted_text("https://datHere.com"), + ); + println!( + "This installer should assist in setting up {} from a source installation along with ckan-compose. If you have any issues, please report them at https://support.dathere.com or https://github.com/dathere/ckan-devstaller/issues.", + highlighted_text("CKAN 2.11.3") + ); + println!( + "{}", + important_text( + "This installer is only intended for a brand new installation of Ubuntu 22.04." + ) + ); +}