diff --git a/src/handlers/playbook.rs b/src/handlers/playbook.rs index 116e003..b1062fa 100644 --- a/src/handlers/playbook.rs +++ b/src/handlers/playbook.rs @@ -12,9 +12,10 @@ // 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}; +use axum::extract::{Path, State}; use axum::http::StatusCode; use axum::response::IntoResponse; use axum::Json; @@ -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. @@ -56,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"), ), @@ -66,28 +67,7 @@ pub async fn detail( Path(params): Path, State(ctx): State>, ) -> Result { - Ok(Json(PlaybookService::get(ctx, params.id, params.reference, params.path).await?)) -} -#[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, true).await?)) } /// Update a playbook. #[utoipa::path( @@ -96,7 +76,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 +89,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 +128,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/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/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 778ccaf..9c1e5d9 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,8 +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..22147c0 100644 --- a/src/services/playbook.rs +++ b/src/services/playbook.rs @@ -16,36 +16,63 @@ 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 url::Url; use uuid::Uuid; use crate::context::Context; use crate::errors::ApiError; -use crate::requests::playbook::{CreatePlaybookRequest, UpdatePlaybookRequest}; +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 { - 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()) + 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(); + match playbook_result { + Some(playbook) => { + 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(); + } + } + } + } + None => { + info!("Not found playbooks in {}...", id); + } + } + Ok(files_response) } 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 +85,32 @@ 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!() + } +} + +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 028fb40..965ef9b 100644 --- a/src/swagger.rs +++ b/src/swagger.rs @@ -24,8 +24,8 @@ use crate::{handlers, requests, responses}; handlers::playbook::detail, handlers::playbook::update, handlers::playbook::delete, - handlers::playbook::trees, handlers::playbook::start, + handlers::playbook::logs, ), components( schemas( @@ -53,6 +53,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(