Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement update #36

Merged
merged 3 commits into from
Jan 17, 2024
Merged
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
55 changes: 27 additions & 28 deletions src/handlers/playbook.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,18 @@
// 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;
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.
Expand Down Expand Up @@ -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"),
),
Expand All @@ -66,28 +67,7 @@ pub async fn detail(
Path(params): Path<GetPlaybookRequest>,
State(ctx): State<Arc<Context>>,
) -> Result<impl IntoResponse> {
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<GetPlaybookRequest>,
Query(recursive): Query<Option<bool>>,
State(ctx): State<Arc<Context>>,
) -> Result<impl IntoResponse> {
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(
Expand All @@ -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"
),
Expand All @@ -109,9 +89,10 @@ pub async fn trees(
pub async fn update(
Path(id): Path<Uuid>,
State(ctx): State<Arc<Context>>,
Json(req): Json<UpdatePlaybookRequest>,
Json(req): Json<Synchronization>,
) -> Result<impl IntoResponse> {
Ok(Json(PlaybookService::update(ctx, id, &req).await?))
PlaybookService::update(ctx, id, req).await?;
Ok(StatusCode::NO_CONTENT)
}

/// Delete a playbook
Expand Down Expand Up @@ -147,3 +128,21 @@ pub async fn start(Path(id): Path<Uuid>, State(ctx): State<Arc<Context>>) -> 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<Uuid>, State(ctx): State<Arc<Context>>) -> Result<impl IntoResponse> {
PlaybookService::logs(ctx, id).await;
Ok(StatusCode::OK)
}
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/requests/playbook.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,5 @@ pub struct UpdatePlaybookRequest {
pub struct GetPlaybookRequest {
pub id: Uuid,
pub reference: String,
pub path: String,
pub path: Option<String>,
}
10 changes: 10 additions & 0 deletions src/responses/playbook.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -29,3 +31,11 @@ pub struct PlaybookResponse {
/// When the playbook was last updated in Amphitheatre.
pub updated_at: DateTime<Utc>,
}

#[derive(Serialize, Deserialize, ToSchema)]
pub struct FilesResponse {
/// The file details.
pub content: Content,
/// The files tree.
pub tree: Tree,
}
5 changes: 2 additions & 3 deletions src/routes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -25,8 +25,7 @@ pub fn build() -> Router<Arc<Context>> {
// 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))
}
84 changes: 66 additions & 18 deletions src/services/playbook.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Context>, id: Uuid, reference: String, path: String) -> Result<Content> {
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<Context>, id: Uuid, reference: String, recursive: Option<bool>) -> Result<Tree> {
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<Context>,
id: Uuid,
reference: String,
path: Option<String>,
recursive: bool,
) -> Result<FilesResponse> {
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<Context>, id: Uuid) -> Result<u16> {
info!("delete playbooks in {}...", id);
ctx.client.playbooks().delete(&id.to_string()).map_err(ApiError::NotFoundPlaybook)
}

Expand All @@ -58,11 +85,32 @@ impl PlaybookService {
ctx.client.playbooks().create(playbook_payload).map_err(ApiError::NotFoundPlaybook)
}

pub async fn update(_ctx: Arc<Context>, _id: Uuid, _req: &UpdatePlaybookRequest) -> Result<PlaybookSpec> {
unimplemented!()
pub async fn update(ctx: Arc<Context>, id: Uuid, req: Synchronization) -> Result<u16> {
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<Context>, id: Uuid) -> Result<u16> {
info!("Start playbooks in {}...", id);
ctx.client.playbooks().start(&id.to_string()).map_err(ApiError::NotFoundPlaybook)
}

pub async fn logs(_ctx: Arc<Context>, _id: Uuid) {
unreachable!()
}
}

fn empty_content() -> Content {
Content { path: String::new(), data: Vec::new(), sha: String::new(), blob_id: String::new() }
}
4 changes: 3 additions & 1 deletion src/swagger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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(
Expand Down
Loading