From 34732b10662a055111159f81ef8c6b4a7a0e993d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=98=89=E8=B1=AA?= Date: Tue, 16 Jan 2024 16:31:56 +0800 Subject: [PATCH 1/3] Implement update --- src/handlers/playbook.rs | 30 ++++++++++++++++++++---- src/routes.rs | 4 ++-- src/services/playbook.rs | 49 ++++++++++++++++++++++++++++++++-------- src/swagger.rs | 3 +++ 4 files changed, 71 insertions(+), 15 deletions(-) diff --git a/src/handlers/playbook.rs b/src/handlers/playbook.rs index 116e003..8166209 100644 --- a/src/handlers/playbook.rs +++ b/src/handlers/playbook.rs @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +use amp_common::sync::Synchronization; use std::sync::Arc; use axum::extract::{Path, Query, State}; @@ -22,7 +23,7 @@ use uuid::Uuid; use super::Result; use crate::context::Context; -use crate::requests::playbook::{CreatePlaybookRequest, GetPlaybookRequest, UpdatePlaybookRequest}; +use crate::requests::playbook::{CreatePlaybookRequest, GetPlaybookRequest}; use crate::services::playbook::PlaybookService; // The Playbooks Service Handlers. @@ -68,6 +69,8 @@ pub async fn detail( ) -> Result { Ok(Json(PlaybookService::get(ctx, params.id, params.reference, params.path).await?)) } + +/// Get file tree #[utoipa::path( get, path = "/v1/playbooks/:id/files/trees/:reference/:path?recursive=true | false", params( @@ -96,7 +99,7 @@ pub async fn trees( ("id" = Uuid, description = "The id of playbook"), ), request_body( - content = inline(UpdatePlaybookRequest), + content = inline(Synchronization), description = "Update playbook request", content_type = "application/json" ), @@ -109,9 +112,10 @@ pub async fn trees( pub async fn update( Path(id): Path, State(ctx): State>, - Json(req): Json, + Json(req): Json, ) -> Result { - Ok(Json(PlaybookService::update(ctx, id, &req).await?)) + PlaybookService::update(ctx, id, req).await?; + Ok(StatusCode::NO_CONTENT) } /// Delete a playbook @@ -147,3 +151,21 @@ pub async fn start(Path(id): Path, State(ctx): State>) -> Res PlaybookService::start(ctx, id).await?; Ok(StatusCode::NO_CONTENT) } + +/// get a playbook logs + +#[utoipa::path( + get, path = "/v1/playbooks/{id}/logs", + params( + ("id" = Uuid, description = "The id of playbook"), + ), + responses( + (status = 200, description = "Playbook logs found successfully"), + (status = 404, description = "Playbook not found") + ), + tag = "Playbooks" +)] +pub async fn logs(Path(id): Path, State(ctx): State>) -> Result { + PlaybookService::logs(ctx, id).await; + Ok(StatusCode::OK) +} diff --git a/src/routes.rs b/src/routes.rs index 778ccaf..12ef47c 100644 --- a/src/routes.rs +++ b/src/routes.rs @@ -14,7 +14,7 @@ use std::sync::Arc; -use axum::routing::{delete, get, patch, post}; +use axum::routing::{delete, get, post, put}; use axum::Router; use crate::context::Context; @@ -25,7 +25,7 @@ pub fn build() -> Router> { // playbooks .route("/v1/playbooks", post(handlers::playbook::create)) .route("/v1/playbooks/:id/files/:reference/:path", get(handlers::playbook::detail)) - .route("/v1/playbooks/:id", patch(handlers::playbook::update)) + .route("/v1/playbooks/:id", put(handlers::playbook::update)) .route("/v1/playbooks/:id", delete(handlers::playbook::delete)) .route("/v1/playbooks/:id/files/trees/:reference/:path", get(handlers::playbook::trees)) .route("/v1/playbooks/:id/actions/start", get(handlers::playbook::start)) diff --git a/src/services/playbook.rs b/src/services/playbook.rs index fb3492c..fa65a1f 100644 --- a/src/services/playbook.rs +++ b/src/services/playbook.rs @@ -16,13 +16,15 @@ use amp_client::playbooks::PlaybookPayload; use amp_common::resource::PlaybookSpec; use amp_common::scm::content::Content; use amp_common::scm::git::Tree; +use amp_common::sync::Synchronization; use std::sync::Arc; +use tracing::info; use uuid::Uuid; use crate::context::Context; use crate::errors::ApiError; -use crate::requests::playbook::{CreatePlaybookRequest, UpdatePlaybookRequest}; +use crate::requests::playbook::CreatePlaybookRequest; use crate::services::Result; pub struct PlaybookService; @@ -37,15 +39,27 @@ impl PlaybookService { } pub async fn trees(ctx: Arc, id: Uuid, reference: String, recursive: Option) -> Result { - let result = ctx.client.playbooks().get(&id.to_string()).map_err(ApiError::NotFoundPlaybook); - let spec = result.unwrap_or_default(); - let repo = spec.preface.repository.unwrap_or_default().repo; - let tree = - ctx.github_client.git().git_trees(repo.as_str(), reference.as_str(), recursive).ok().unwrap_or_default(); - Ok(tree.unwrap_or_default()) + let playbook_result = ctx.client.playbooks().get(&id.to_string()).map_err(ApiError::NotFoundPlaybook).ok(); + return match playbook_result { + Some(playbook) => { + let repo = playbook.preface.repository.unwrap_or_default().repo; + let tree = ctx + .github_client + .git() + .git_trees(repo.as_str(), reference.as_str(), recursive) + .ok() + .unwrap_or_default(); + Ok(tree.unwrap_or_default()) + } + None => { + info!("Not found playbooks in {}...", id); + Ok(Tree::default()) + } + }; } pub async fn delete(ctx: Arc, id: Uuid) -> Result { + info!("delete playbooks in {}...", id); ctx.client.playbooks().delete(&id.to_string()).map_err(ApiError::NotFoundPlaybook) } @@ -58,11 +72,28 @@ impl PlaybookService { ctx.client.playbooks().create(playbook_payload).map_err(ApiError::NotFoundPlaybook) } - pub async fn update(_ctx: Arc, _id: Uuid, _req: &UpdatePlaybookRequest) -> Result { - unimplemented!() + pub async fn update(ctx: Arc, id: Uuid, req: Synchronization) -> Result { + let playbook_result = ctx.client.playbooks().get(&id.to_string()).map_err(ApiError::NotFoundPlaybook).ok(); + return match playbook_result { + Some(playbook) => { + info!("update playbooks in {}...", id); + let uuid_str: &str = &id.to_string(); + let name = playbook.preface.name.as_str(); + ctx.client.actors().sync(uuid_str, name, req).map_err(ApiError::NotFoundPlaybook) + } + None => { + info!("Not found playbooks in {}...", id); + Ok(0) + } + }; } pub async fn start(ctx: Arc, id: Uuid) -> Result { + info!("Start playbooks in {}...", id); ctx.client.playbooks().start(&id.to_string()).map_err(ApiError::NotFoundPlaybook) } + + pub async fn logs(_ctx: Arc, _id: Uuid) { + unreachable!() + } } diff --git a/src/swagger.rs b/src/swagger.rs index 028fb40..00692d2 100644 --- a/src/swagger.rs +++ b/src/swagger.rs @@ -26,6 +26,7 @@ use crate::{handlers, requests, responses}; handlers::playbook::delete, handlers::playbook::trees, handlers::playbook::start, + handlers::playbook::logs, ), components( schemas( @@ -53,6 +54,8 @@ use crate::{handlers, requests, responses}; amp_common::scm::content::Content, amp_common::scm::git::Tree, amp_common::scm::git::TreeEntry, + + amp_common::sync::Synchronization, ) ), tags( From 96b4427c008e0cbe9f7137f410405ff102cffc79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=98=89=E8=B1=AA?= Date: Wed, 17 Jan 2024 19:04:22 +0800 Subject: [PATCH 2/3] trees merge content --- src/handlers/playbook.rs | 28 +++----------------- src/requests/playbook.rs | 2 +- src/responses/playbook.rs | 10 ++++++++ src/routes.rs | 1 - src/services/playbook.rs | 54 +++++++++++++++++++++++++-------------- src/swagger.rs | 1 - 6 files changed, 49 insertions(+), 47 deletions(-) diff --git a/src/handlers/playbook.rs b/src/handlers/playbook.rs index 8166209..ac23a83 100644 --- a/src/handlers/playbook.rs +++ b/src/handlers/playbook.rs @@ -57,7 +57,7 @@ pub async fn create( ("path" = String, description = "path parameter"), ), responses( - (status = 200, description = "Playbook found successfully", body = Content), + (status = 200, description = "Playbook found successfully", body = FilesResponse), (status = 404, description = "Playbook not found"), (status = 500, description = "Internal Server Error"), ), @@ -65,32 +65,10 @@ pub async fn create( )] pub async fn detail( Path(params): Path, + Query(recursive): Query, State(ctx): State>, ) -> Result { - Ok(Json(PlaybookService::get(ctx, params.id, params.reference, params.path).await?)) -} - -/// Get file tree -#[utoipa::path( -get, path = "/v1/playbooks/:id/files/trees/:reference/:path?recursive=true | false", - params( - ("id" = Uuid, description = "The id of playbook"), - ("reference" = String, description = "The name of the commit/branch/tag. Default: the repository’s default branch."), - ("path" = String, description = "path parameter"), - ), - responses( - (status = 200, description = "Playbook found successfully", body = Tree), - (status = 404, description = "Playbook not found"), - (status = 500, description = "Internal Server Error"), - ), - tag = "Playbooks" -)] -pub async fn trees( - Path(params): Path, - Query(recursive): Query>, - State(ctx): State>, -) -> Result { - Ok(Json(PlaybookService::trees(ctx, params.id, params.reference, recursive).await?)) + Ok(Json(PlaybookService::get(ctx, params.id, params.reference, params.path, recursive).await?)) } /// Update a playbook. #[utoipa::path( diff --git a/src/requests/playbook.rs b/src/requests/playbook.rs index 2d6dc5d..7973d42 100644 --- a/src/requests/playbook.rs +++ b/src/requests/playbook.rs @@ -34,5 +34,5 @@ pub struct UpdatePlaybookRequest { pub struct GetPlaybookRequest { pub id: Uuid, pub reference: String, - pub path: String, + pub path: Option, } diff --git a/src/responses/playbook.rs b/src/responses/playbook.rs index fe3bbe9..f53b570 100644 --- a/src/responses/playbook.rs +++ b/src/responses/playbook.rs @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +use amp_common::scm::content::Content; +use amp_common::scm::git::Tree; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use utoipa::ToSchema; @@ -29,3 +31,11 @@ pub struct PlaybookResponse { /// When the playbook was last updated in Amphitheatre. pub updated_at: DateTime, } + +#[derive(Serialize, Deserialize, ToSchema)] +pub struct FilesResponse { + /// The file details. + pub content: Content, + /// The files tree. + pub tree: Tree, +} diff --git a/src/routes.rs b/src/routes.rs index 12ef47c..9c1e5d9 100644 --- a/src/routes.rs +++ b/src/routes.rs @@ -27,6 +27,5 @@ pub fn build() -> Router> { .route("/v1/playbooks/:id/files/:reference/:path", get(handlers::playbook::detail)) .route("/v1/playbooks/:id", put(handlers::playbook::update)) .route("/v1/playbooks/:id", delete(handlers::playbook::delete)) - .route("/v1/playbooks/:id/files/trees/:reference/:path", get(handlers::playbook::trees)) .route("/v1/playbooks/:id/actions/start", get(handlers::playbook::start)) } diff --git a/src/services/playbook.rs b/src/services/playbook.rs index fa65a1f..55b5ea2 100644 --- a/src/services/playbook.rs +++ b/src/services/playbook.rs @@ -25,37 +25,49 @@ use uuid::Uuid; use crate::context::Context; use crate::errors::ApiError; use crate::requests::playbook::CreatePlaybookRequest; +use crate::responses::playbook::FilesResponse; use crate::services::Result; pub struct PlaybookService; impl PlaybookService { - pub async fn get(ctx: Arc, id: Uuid, reference: String, path: String) -> Result { - let result = ctx.client.playbooks().get(&id.to_string()).map_err(ApiError::NotFoundPlaybook); - let spec = result.unwrap_or_default(); - let repo = spec.preface.repository.unwrap_or_default().repo; - let content = ctx.github_client.contents().find(repo.as_str(), path.as_str(), reference.as_str()).ok(); - Ok(content.unwrap()) - } - - pub async fn trees(ctx: Arc, id: Uuid, reference: String, recursive: Option) -> Result { + pub async fn get( + ctx: Arc, + id: Uuid, + reference: String, + path: Option, + recursive: bool, + ) -> Result { + let mut files_response = FilesResponse { content: empty_content(), tree: Tree::default() }; let playbook_result = ctx.client.playbooks().get(&id.to_string()).map_err(ApiError::NotFoundPlaybook).ok(); - return match playbook_result { + match playbook_result { Some(playbook) => { let repo = playbook.preface.repository.unwrap_or_default().repo; - let tree = ctx - .github_client - .git() - .git_trees(repo.as_str(), reference.as_str(), recursive) - .ok() - .unwrap_or_default(); - Ok(tree.unwrap_or_default()) + match path.is_some() { + true => { + let content = ctx + .github_client + .contents() + .find(repo.as_str(), path.unwrap().as_str(), reference.as_str()) + .ok(); + files_response.content = content.unwrap_or(empty_content()); + } + false => { + let tree = ctx + .github_client + .git() + .git_trees(repo.as_str(), reference.as_str(), Option::from(recursive)) + .ok() + .unwrap_or_default(); + files_response.tree = tree.unwrap_or_default(); + } + } } None => { info!("Not found playbooks in {}...", id); - Ok(Tree::default()) } - }; + } + Ok(files_response) } pub async fn delete(ctx: Arc, id: Uuid) -> Result { @@ -97,3 +109,7 @@ impl PlaybookService { unreachable!() } } + +fn empty_content() -> Content { + Content { path: String::new(), data: Vec::new(), sha: String::new(), blob_id: String::new() } +} diff --git a/src/swagger.rs b/src/swagger.rs index 00692d2..965ef9b 100644 --- a/src/swagger.rs +++ b/src/swagger.rs @@ -24,7 +24,6 @@ use crate::{handlers, requests, responses}; handlers::playbook::detail, handlers::playbook::update, handlers::playbook::delete, - handlers::playbook::trees, handlers::playbook::start, handlers::playbook::logs, ), From b6f453439a64b510e2a91a2be5d905ddefa952d3 Mon Sep 17 00:00:00 2001 From: jiahao6635 Date: Thu, 18 Jan 2024 01:06:39 +0800 Subject: [PATCH 3/3] debugging interface --- src/handlers/playbook.rs | 5 ++--- src/main.rs | 2 +- src/services/playbook.rs | 39 ++++++++++++++++++++------------------- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/handlers/playbook.rs b/src/handlers/playbook.rs index ac23a83..b1062fa 100644 --- a/src/handlers/playbook.rs +++ b/src/handlers/playbook.rs @@ -15,7 +15,7 @@ use amp_common::sync::Synchronization; use std::sync::Arc; -use axum::extract::{Path, Query, State}; +use axum::extract::{Path, State}; use axum::http::StatusCode; use axum::response::IntoResponse; use axum::Json; @@ -65,10 +65,9 @@ pub async fn create( )] pub async fn detail( Path(params): Path, - Query(recursive): Query, State(ctx): State>, ) -> Result { - Ok(Json(PlaybookService::get(ctx, params.id, params.reference, params.path, recursive).await?)) + Ok(Json(PlaybookService::get(ctx, params.id, params.reference, params.path, true).await?)) } /// Update a playbook. #[utoipa::path( diff --git a/src/main.rs b/src/main.rs index 7ceaeb0..ace6406 100644 --- a/src/main.rs +++ b/src/main.rs @@ -23,7 +23,7 @@ use tracing_subscriber::EnvFilter; #[tokio::main] async fn main() -> anyhow::Result<()> { - let filter = EnvFilter::builder().with_default_directive(LevelFilter::INFO.into()).from_env_lossy(); + let filter = EnvFilter::builder().with_default_directive(LevelFilter::DEBUG.into()).from_env_lossy(); tracing_subscriber::fmt().with_env_filter(filter).init(); // This returns an error if the `.env` file doesn't exist, but that's not what we want diff --git a/src/services/playbook.rs b/src/services/playbook.rs index 55b5ea2..22147c0 100644 --- a/src/services/playbook.rs +++ b/src/services/playbook.rs @@ -18,7 +18,8 @@ use amp_common::scm::content::Content; use amp_common::scm::git::Tree; use amp_common::sync::Synchronization; use std::sync::Arc; -use tracing::info; +use tracing::{info}; +use url::Url; use uuid::Uuid; @@ -42,24 +43,24 @@ impl PlaybookService { let playbook_result = ctx.client.playbooks().get(&id.to_string()).map_err(ApiError::NotFoundPlaybook).ok(); match playbook_result { Some(playbook) => { - let repo = playbook.preface.repository.unwrap_or_default().repo; - match path.is_some() { - true => { - let content = ctx - .github_client - .contents() - .find(repo.as_str(), path.unwrap().as_str(), reference.as_str()) - .ok(); - files_response.content = content.unwrap_or(empty_content()); - } - false => { - let tree = ctx - .github_client - .git() - .git_trees(repo.as_str(), reference.as_str(), Option::from(recursive)) - .ok() - .unwrap_or_default(); - files_response.tree = tree.unwrap_or_default(); + let repository = playbook.preface.manifest.unwrap_or_default().meta.repository; + if let Ok(url) = Url::parse(repository.as_str()) { + let repo = &url.path()[1..]; + match path.is_some() { + true => { + let content = + ctx.github_client.contents().find(repo, path.unwrap().as_str(), reference.as_str()).ok(); + files_response.content = content.unwrap_or(empty_content()); + } + false => { + let tree = ctx + .github_client + .git() + .git_trees(repo, reference.as_str(), Option::from(recursive)) + .ok() + .unwrap_or_default(); + files_response.tree = tree.unwrap_or_default(); + } } } }