Skip to content
This repository has been archived by the owner on Jul 2, 2024. It is now read-only.

feat(webui): create a new project from web dashboard #59

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
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
1,411 changes: 1,295 additions & 116 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<img alt="release" src="https://github.com/tsirysndr/superviseur/actions/workflows/release.yml/badge.svg" />
</a>
<a href="https://discord.gg/FeGJerUC" target="_blank">
<img alt="discord-server" src="https://img.shields.io/discord/1026789060515205181?label=discord&logo=discord&color=5865F2">
<img alt="discord-server" src="https://img.shields.io/discord/1103720908104929321?label=discord&logo=discord&color=5865F2">
</a>
</p>

Expand Down
31 changes: 31 additions & 0 deletions crates/cli/src/cmd/code.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use anyhow::Error;
use superviseur_server::api::superviseur::v1alpha1::{project_service_client::ProjectServiceClient, OpenProjectRequest};
use superviseur_types::UNIX_SOCKET_PATH;
use tokio::net::UnixStream;
use tonic::transport::{ Endpoint, Uri};
use tower::service_fn;

pub async fn execute_code(name: &str) -> Result<(), Error> {
let channel = Endpoint::try_from("http://[::]:50051")?
.connect_with_connector(service_fn(move |_: Uri| UnixStream::connect(UNIX_SOCKET_PATH)))
.await
.map_err(|_|
Error::msg(format!("Cannot connect to the Superviseur daemon at unix:{}. Is the superviseur daemon running?", UNIX_SOCKET_PATH)))?;

let mut client = ProjectServiceClient::new(channel);
let request = tonic::Request::new(OpenProjectRequest {
id: name.to_string(),
});
let response = client.open_project(request).await?;
let mut stream = response.into_inner();

while let Some(message) = stream.message().await? {
println!("{}", message.line);
if message.line.starts_with("Open this link in your browser") {
let link = message.line.replace("Open this link in your browser ", "");
open::that(&link)?;
}
}

Ok(())
}
1 change: 1 addition & 0 deletions crates/cli/src/cmd/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod build;
pub mod code;
pub mod config;
pub mod init;
pub mod list;
Expand Down
37 changes: 19 additions & 18 deletions crates/cli/src/cmd/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,29 @@ use superviseur_types::{BANNER, UNIX_SOCKET_PATH};
use crate::config::verify_if_config_file_is_present;

pub async fn execute_ui() -> Result<(), Error> {
let (config, config_format) = verify_if_config_file_is_present()?;
let current_dir = std::env::current_dir()?;
let mut config_file_path = "";
let current_dir = std::env::current_dir()?;
let channel = Endpoint::try_from("http://[::]:50051")?
.connect_with_connector(service_fn(move |_: Uri| UnixStream::connect(UNIX_SOCKET_PATH)))
.await
.map_err(|_|
Error::msg(format!("Cannot connect to the Superviseur daemon at unix:{}. Is the superviseur daemon running?", UNIX_SOCKET_PATH)))?;

// let mut client = ControlServiceClient::connect("http://127.0.0.1:5476").await?;

let mut client = ControlServiceClient::new(channel.clone());

let request = tonic::Request::new(LoadConfigRequest {
config,
file_path: current_dir.to_str().unwrap().to_string(),
config_format
});
client.load_config(request).await?;
.connect_with_connector(service_fn(move |_: Uri| UnixStream::connect(UNIX_SOCKET_PATH)))
.await
.map_err(|_|
Error::msg(format!("Cannot connect to the Superviseur daemon at unix:{}. Is the superviseur daemon running?", UNIX_SOCKET_PATH)))?;

if let Ok((config, config_format)) = verify_if_config_file_is_present() {
let mut client = ControlServiceClient::new(channel.clone());

let request = tonic::Request::new(LoadConfigRequest {
config,
file_path: current_dir.to_str().unwrap().to_string(),
config_format
});
client.load_config(request).await?;
config_file_path = current_dir.to_str().unwrap();
}

let mut client = CoreServiceClient::new(channel);
let request = tonic::Request::new(StartWebDashboardRequest {
config_file_path: current_dir.to_str().unwrap().to_string(),
config_file_path: config_file_path.to_string(),
});
let response = client.start_web_dashboard(request).await?;
let response = response.into_inner();
Expand Down
10 changes: 10 additions & 0 deletions crates/cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use crate::cmd::{
};
use anyhow::Error;
use clap::{arg, Command, SubCommand};
use cmd::code::execute_code;
use superviseur_server::server;
use superviseur_types::configuration::ConfigFormat;

Expand Down Expand Up @@ -131,6 +132,11 @@ Define and run multi-service applications on isolated environments with Nix or D
.arg(arg!(<query> "The query to search"))
.about("Search the log of a service"),
)
.subcommand(
Command::new("code")
.arg(arg!(<name> "The name of the project to open in VSCode"))
.about("Open a project in VSCode"),
)
}

#[tokio::main]
Expand Down Expand Up @@ -214,6 +220,10 @@ async fn main() -> Result<(), Error> {
let query = args.value_of("query");
execute_search_log(name.unwrap(), query.unwrap()).await?;
}
Some(("code", args)) => {
let name = args.value_of("name");
execute_code(name.unwrap()).await?;
}
_ => cli().print_help()?,
}
Ok(())
Expand Down
16 changes: 16 additions & 0 deletions crates/code/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
authors = ["Tsiry Sandratraina <[email protected]>"]
categories = ["command-line-utilities"]
description = "A plugin to spawn a vscode tunnel for superviseur project"
edition = "2021"
keywords = ["tunnel", "supervisor", "cli", "vscode"]
license = "MPL-2.0"
name = "superviseur-code"
repository = "https://github.com/tsirysndr/superviseur"
version = "0.1.0"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
anyhow = "1.0.71"
tokio = {version = "1.24.2", features = ["tokio-macros", "macros", "rt", "rt-multi-thread", "sync"]}
56 changes: 56 additions & 0 deletions crates/code/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use anyhow::Error;
use std::{io::BufRead, process::Command, thread};
use tokio::sync::mpsc::UnboundedSender;

pub fn start_code_tunnel(sender: UnboundedSender<String>, dir: &str) -> Result<u32, Error> {
verify_if_code_is_installed()?;

let mut child = Command::new("code")
.arg("tunnel")
.arg("--accept-server-license-terms")
.current_dir(dir)
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.spawn()
.expect("failed to execute process");

let pid = child.id();

thread::spawn(move || {
let stdout = child.stdout.take().expect("Failed to get stdout handle");
let stderr = child.stderr.take().expect("Failed to get stderr handle");
let stdout_reader = std::io::BufReader::new(stdout);
let stderr_reader = std::io::BufReader::new(stderr);

for line in stdout_reader.lines() {
if let Ok(line) = line {
sender.send(line).unwrap();
}
}

for line in stderr_reader.lines() {
if let Ok(line) = line {
sender.send(line).unwrap();
}
}

drop(sender);

child.wait().expect("Failed to wait on child");
});

Ok(pid)
}

fn verify_if_code_is_installed() -> Result<(), Error> {
let output = Command::new("code")
.arg("--version")
.output()
.expect("failed to execute process");

if !output.status.success() {
return Err(Error::msg("Code is not installed"));
}

Ok(())
}
4 changes: 4 additions & 0 deletions crates/graphql/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,19 @@ version = "0.1.0"
anyhow = "1.0.69"
async-graphql = "5.0.6"
async-graphql-actix-web = "5.0.6"
dirs = "5.0.1"
futures = "0.3.26"
futures-channel = "0.3.26"
futures-util = "0.3.26"
hcl-rs = "0.14.2"
indexmap = {version = "1.9.2", features = ["serde"]}
names = "0.14.0"
once_cell = "1.17.1"
slab = "0.4.8"
superviseur-code = {path = "../code", version = "0.1.0"}
superviseur-macros = {path = "../macros", version = "0.1.0"}
superviseur-provider = {path = "../provider", version = "0.1.0"}
superviseur-template = {path = "../template", version = "0.1.0"}
superviseur-types = {path = "../types", version = "0.1.0"}
superviseur-util = {path = "../util", version = "0.1.0"}
tokio = {version = "1.24.2", features = ["tokio-macros", "macros", "rt", "rt-multi-thread"]}
Expand Down
41 changes: 41 additions & 0 deletions crates/graphql/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,45 @@ macro_rules! project_exists {
};
}

macro_rules! send_event {
($project:expr, $services:expr,$cmd_tx:ident, $command:ident, $event:ident) => {
for (_, service) in &$services {
$cmd_tx
.send(SuperviseurCommand::$command(
service.clone(),
$project.clone(),
))
.unwrap();
}
let services = $services.clone();
let services = services
.iter()
.map(|(_, x)| Service::from(x))
.collect::<Vec<Service>>();
SimpleBroker::publish($event { payload: services });
};
}

macro_rules! send_event_alt {
($project:expr, $services:expr,$cmd_tx:ident, $command:ident, $event:ident) => {
for (_, service) in &$services {
$cmd_tx
.send(SuperviseurCommand::$command(
service.clone(),
$project.clone(),
true,
))
.unwrap();
}
let services = $services.clone();
let services = services
.iter()
.map(|(_, x)| Service::from(x))
.collect::<Vec<Service>>();
SimpleBroker::publish($event { payload: services });
};
}

pub(crate) use project_exists;
pub(crate) use send_event;
pub(crate) use send_event_alt;
Loading