Skip to content

Commit

Permalink
feat: Implement separate function for API request samples (#2077)
Browse files Browse the repository at this point in the history
* chore: Add API urls

* Add sample commands

* Minor changes

* Implement separate function for API request samples

* Remove unnecessary clone

* Fix format

---------

Signed-off-by: Karolis Gudiškis <[email protected]>
  • Loading branch information
karolisg authored Sep 22, 2023
1 parent 24d413a commit c2ec780
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 7 deletions.
6 changes: 6 additions & 0 deletions dozer-cli/src/cli/cloud.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ pub enum CloudCommands {
/// Dozer app secrets management
#[command(subcommand)]
Secrets(SecretsCommand),
/// Get example of API call
#[command(name = "api-request-samples")]
ApiRequestSamples {
#[arg(long, short)]
endpoint: Option<String>,
},
}

#[derive(Debug, Args, Clone)]
Expand Down
4 changes: 2 additions & 2 deletions dozer-cli/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ pub enum OrchestrationError {
GenerateTokenFailed(#[source] AuthError),
#[error("Missing api config or security input")]
MissingSecurityConfig,
#[error("Cloud service error: {0}")]
#[error(transparent)]
CloudError(#[from] CloudError),
#[error("Failed to initialize api server: {0}")]
ApiInitFailed(#[from] ApiInitError),
Expand Down Expand Up @@ -142,7 +142,7 @@ pub enum CloudError {
#[error("Connection failed. Error: {0:?}")]
ConnectionToCloudServiceError(#[from] tonic::transport::Error),

#[error("Cloud service returned error: {0:?}")]
#[error("Cloud service returned error: {}", .0.message())]
CloudServiceError(#[from] tonic::Status),

#[error("GRPC request failed, error: {} (GRPC status {})", .0.message(), .0.code())]
Expand Down
3 changes: 3 additions & 0 deletions dozer-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,9 @@ fn run() -> Result<(), OrchestrationError> {
info!("Using \"{app_id}\" app");
Ok(())
}
CloudCommands::ApiRequestSamples { endpoint } => {
dozer.print_api_request_samples(cloud, endpoint)
}
}
}
Commands::Init => {
Expand Down
12 changes: 9 additions & 3 deletions dozer-cli/src/simple/cloud/deployer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ use dozer_types::grpc_types::cloud::dozer_cloud_client::DozerCloudClient;
use dozer_types::grpc_types::cloud::DeploymentStatus;
use dozer_types::grpc_types::cloud::GetDeploymentStatusRequest;

use crate::cloud_app_context::CloudAppContext;
use dozer_types::grpc_types::cloud::DeployAppRequest;
use dozer_types::grpc_types::cloud::File;
use dozer_types::grpc_types::cloud::{Secret, StopRequest, StopResponse};
use dozer_types::log::info;
use dozer_types::log::{info, warn};

pub async fn deploy_app(
client: &mut DozerCloudClient<TokenLayer>,
Expand Down Expand Up @@ -50,7 +51,7 @@ async fn print_progress(
let mut current_step = 0;
let mut printer = ProgressPrinter::new();
let request = GetDeploymentStatusRequest {
app_id,
app_id: app_id.clone(),
deployment_id,
};
loop {
Expand All @@ -61,9 +62,13 @@ async fn print_progress(

if response.status == DeploymentStatus::Success as i32 {
info!("Deployment completed successfully");
info!("You can get API requests samples with `dozer cloud api-request-samples`");

CloudAppContext::save_app_id(app_id)?;

break;
} else if response.status == DeploymentStatus::Failed as i32 {
info!("Deployment failed!");
warn!("Deployment failed!");
break;
} else {
let steps = response.steps.clone();
Expand All @@ -86,6 +91,7 @@ async fn print_progress(
printer.start_step(current_step, &text);
}
}

tokio::time::sleep(std::time::Duration::from_millis(500)).await;
}
Ok::<(), CloudError>(())
Expand Down
92 changes: 90 additions & 2 deletions dozer-cli/src/simple/cloud_orchestrator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::cli::cloud::{
use crate::cloud_app_context::CloudAppContext;
use crate::cloud_helper::list_files;

use crate::console_helper::{get_colored_text, PURPLE};
use crate::errors::OrchestrationError::FailedToReadOrganisationName;
use crate::errors::{map_tonic_error, CliError, CloudError, CloudLoginError, OrchestrationError};
use crate::simple::cloud::deployer::{deploy_app, stop_app};
Expand All @@ -13,10 +14,12 @@ use crate::simple::token_layer::TokenLayer;
use crate::simple::SimpleOrchestrator;
use crate::CloudOrchestrator;
use dozer_types::constants::{DEFAULT_CLOUD_TARGET_URL, LOCK_FILE};
use dozer_types::grpc_types::api_explorer::api_explorer_service_client::ApiExplorerServiceClient;
use dozer_types::grpc_types::api_explorer::GetApiTokenRequest;
use dozer_types::grpc_types::cloud::{
dozer_cloud_client::DozerCloudClient, CreateSecretRequest, DeleteAppRequest,
DeleteSecretRequest, GetSecretRequest, GetStatusRequest, ListAppRequest, ListSecretsRequest,
LogMessageRequest, UpdateSecretRequest,
DeleteSecretRequest, GetEndpointCommandsSamplesRequest, GetSecretRequest, GetStatusRequest,
ListAppRequest, ListSecretsRequest, LogMessageRequest, UpdateSecretRequest,
};
use dozer_types::grpc_types::cloud::{
DeploymentInfo, DeploymentStatusWithHealth, File, ListDeploymentRequest,
Expand Down Expand Up @@ -56,6 +59,30 @@ pub async fn get_cloud_client(
Ok(client)
}

pub async fn get_explorer_client(
cloud: &Cloud,
cloud_config: Option<&dozer_types::models::cloud::Cloud>,
) -> Result<ApiExplorerServiceClient<TokenLayer>, CloudError> {
let profile_name = match &cloud.profile {
None => cloud_config.as_ref().and_then(|c| c.profile.clone()),
Some(_) => cloud.profile.clone(),
};
let credential = CredentialInfo::load(profile_name)?;
let target_url = cloud
.target_url
.as_ref()
.unwrap_or(&credential.target_url)
.clone();

let endpoint = Endpoint::from_shared(target_url.to_owned())?;
let channel = Endpoint::connect(&endpoint).await?;
let channel = ServiceBuilder::new()
.layer_fn(|channel| TokenLayer::new(channel, credential.clone()))
.service(channel);
let client = ApiExplorerServiceClient::new(channel);
Ok(client)
}

impl CloudOrchestrator for SimpleOrchestrator {
// TODO: Deploy Dozer application using local Dozer configuration
fn deploy(
Expand All @@ -78,6 +105,7 @@ impl CloudOrchestrator for SimpleOrchestrator {
let lockfile_path = self.lockfile_path();
self.runtime.block_on(async move {
let mut client = get_cloud_client(&cloud, cloud_config).await?;
// let mut explorer_client = get_explorer_client(&cloud, cloud_config).await?;
let mut files = list_files(config_paths)?;
if deploy.locked {
let lockfile_contents = tokio::fs::read_to_string(lockfile_path)
Expand All @@ -99,6 +127,7 @@ impl CloudOrchestrator for SimpleOrchestrator {
// 2. START application
deploy_app(
&mut client,
// &mut explorer_client,
&app_id,
deploy.secrets,
deploy.allow_incompatible,
Expand Down Expand Up @@ -576,6 +605,65 @@ impl SimpleOrchestrator {
})?;
Ok(())
}

pub fn print_api_request_samples(
&self,
cloud: Cloud,
endpoint: Option<String>,
) -> Result<(), OrchestrationError> {
let app_id = cloud
.app_id
.clone()
.unwrap_or(CloudAppContext::get_app_id(self.config.cloud.as_ref())?);
let cloud_config = self.config.cloud.as_ref();
self.runtime.block_on(async move {
let mut client = get_cloud_client(&cloud, cloud_config).await?;
let mut explorer_client = get_explorer_client(&cloud, cloud_config).await?;

let response = client
.get_endpoint_commands_samples(GetEndpointCommandsSamplesRequest {
app_id: app_id.clone(),
endpoint,
})
.await
.map_err(map_tonic_error)?
.into_inner();

let token_response = explorer_client
.get_api_token(GetApiTokenRequest {
app_id: Some(app_id),
ttl: Some(3600),
})
.await?
.into_inner();

let mut rows = vec![];
let token = match token_response.token {
Some(token) => token,
None => {
info!("Replace $DOZER_TOKEN with your API authorization token");
"$DOZER_TOKEN".to_string()
}
};

for sample in response.samples {
rows.push(get_colored_text(
&format!(
"\n##################### {} command ###########################\n",
sample.r#type
),
PURPLE,
));
rows.push(sample.command.replace("{token}", &token).to_string());
}

info!("{}", rows.join("\n"));

Ok::<(), CloudError>(())
})?;

Ok(())
}
}

fn latest_deployment(deployments: &[DeploymentInfo]) -> Option<u32> {
Expand Down
17 changes: 17 additions & 0 deletions dozer-types/protos/cloud.proto
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ service DozerCloud {

rpc list_notifications(ListNotificationsRequest) returns (ListNotificationsResponse);
rpc mark_notifications_as_read(MarkNotificationsRequest) returns (MarkNotificationsResponse);

rpc get_endpoint_commands_samples(GetEndpointCommandsSamplesRequest) returns (GetEndpointCommandsSamplesResponse);
}

service DozerPublic {
Expand Down Expand Up @@ -352,3 +354,18 @@ message ListSecretsRequest {
message ListSecretsResponse {
repeated string secrets = 1;
}

message CommandSample {
string type = 1;
string command = 2;
optional string description = 3;
}

message GetEndpointCommandsSamplesRequest {
string app_id = 1;
optional string endpoint = 2;
}

message GetEndpointCommandsSamplesResponse {
repeated CommandSample samples = 1;
}

0 comments on commit c2ec780

Please sign in to comment.