Skip to content
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
8 changes: 8 additions & 0 deletions openstack_tui/src/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pub enum Resource {
ComputeServerConsoleOutput(String),
ComputeQuota,
IdentityAuthProjects(IdentityAuthProjectFilters),
IdentityProjects(IdentityProjectFilters),
ImageImages(ImageFilters),
NetworkNetworks(NetworkNetworkFilters),
NetworkSubnets(NetworkSubnetFilters),
Expand Down Expand Up @@ -118,6 +119,13 @@ impl fmt::Display for IdentityAuthProjectFilters {
write!(f, "")
}
}
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct IdentityProjectFilters {}
impl fmt::Display for IdentityProjectFilters {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "")
}
}

#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ImageFilters {
Expand Down
8 changes: 5 additions & 3 deletions openstack_tui/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ use crate::{
components::{
cloud_select_popup::CloudSelect, compute::flavors::ComputeFlavors,
compute::servers::ComputeServers, describe::Describe, error_popup::ErrorPopup,
header::Header, home::Home, image::images::Images, network::networks::NetworkNetworks,
network::subnets::NetworkSubnets, project_select_popup::ProjectSelect,
resource_select_popup::ResourceSelect, Component,
header::Header, home::Home, identity::projects::IdentityProjects, image::images::Images,
network::networks::NetworkNetworks, network::subnets::NetworkSubnets,
project_select_popup::ProjectSelect, resource_select_popup::ResourceSelect, Component,
},
config::Config,
mode::Mode,
Expand Down Expand Up @@ -73,6 +73,7 @@ impl App {
let describe_component: Box<dyn Component> = Box::new(Describe::new());
let compute_servers_component: Box<dyn Component> = Box::new(ComputeServers::new());
let compute_flavors_component: Box<dyn Component> = Box::new(ComputeFlavors::new());
let identity_projects_component: Box<dyn Component> = Box::new(IdentityProjects::new());
let image_images_component: Box<dyn Component> = Box::new(Images::new());
let network_component: Box<dyn Component> = Box::new(NetworkNetworks::new());
let subnet_component: Box<dyn Component> = Box::new(NetworkSubnets::new());
Expand All @@ -99,6 +100,7 @@ impl App {
(Mode::ComputeFlavors, compute_flavors_component),
(Mode::NetworkNetworks, network_component),
(Mode::NetworkSubnets, subnet_component),
(Mode::IdentityProjects, identity_projects_component),
(Mode::ImageImages, image_images_component),
]),
header: Box::new(Header::new()),
Expand Down
9 changes: 7 additions & 2 deletions openstack_tui/src/cloud_services.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ use eyre::Result;
use serde_json::Value;

use crate::action::{
ComputeFlavorFilters, ComputeServerFilters, IdentityAuthProjectFilters, ImageFilters,
NetworkNetworkFilters, NetworkSubnetFilters,
ComputeFlavorFilters, ComputeServerFilters, IdentityAuthProjectFilters, IdentityProjectFilters,
ImageFilters, NetworkNetworkFilters, NetworkSubnetFilters,
};

mod compute;
Expand All @@ -33,6 +33,11 @@ pub trait ComputeExt {
}

pub trait IdentityExt {
async fn get_identity_projects(
&mut self,
_filters: &IdentityProjectFilters,
) -> Result<Vec<Value>>;

async fn get_identity_auth_projects(
&mut self,
filters: &IdentityAuthProjectFilters,
Expand Down
20 changes: 19 additions & 1 deletion openstack_tui/src/cloud_services/identity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,29 @@ use serde_json::Value;

use openstack_sdk::api::QueryAsync;

use crate::action::IdentityAuthProjectFilters;
use crate::action::{IdentityAuthProjectFilters, IdentityProjectFilters};
use crate::cloud_services::IdentityExt;
use crate::cloud_worker::Cloud;

impl IdentityExt for Cloud {
async fn get_identity_projects(
&mut self,
_filters: &IdentityProjectFilters,
) -> Result<Vec<Value>> {
if let Some(session) = &self.cloud {
let ep_builder = openstack_sdk::api::identity::v3::project::list::Request::builder();

//if let Some(vis) = &filters.visibility {
// ep_builder.visibility(vis);
//}
let ep = ep_builder.build()?;
let res: Vec<Value> = ep.query_async(session).await?;
//let res: Vec<Value> = ep.query_async(session).await?;
return Ok(res);
}
Ok(Vec::new())
}

async fn get_identity_auth_projects(
&mut self,
_filters: &IdentityAuthProjectFilters,
Expand Down
11 changes: 11 additions & 0 deletions openstack_tui/src/cloud_worker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,17 @@ impl Cloud {
)))?,
}
}
Resource::IdentityProjects(ref filters) => {
match self.get_identity_projects(filters).await {
Ok(data) => {
app_tx.send(Action::ResourcesData { resource, data })?
}
Err(err) => app_tx.send(Action::Error(format!(
"Failed to fetch available projects: {:?}",
err
)))?,
}
}
Resource::ImageImages(ref filters) => {
match self.get_image_images(filters).await {
Ok(data) => {
Expand Down
1 change: 1 addition & 0 deletions openstack_tui/src/components.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pub mod describe;
pub mod error_popup;
pub mod header;
pub mod home;
pub mod identity;
pub mod image;
pub mod network;
pub mod project_select_popup;
Expand Down
15 changes: 15 additions & 0 deletions openstack_tui/src/components/identity.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0

pub mod projects;
125 changes: 125 additions & 0 deletions openstack_tui/src/components/identity/projects.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0

use crossterm::event::{KeyCode, KeyEvent, KeyEventKind};
use eyre::Result;
use ratatui::prelude::*;
use serde::Deserialize;
use structable_derive::StructTable;
use tokio::sync::mpsc::UnboundedSender;

use crate::{
action::{Action, IdentityProjectFilters, Resource},
components::{table_view::TableViewComponentBase, Component},
config::Config,
mode::Mode,
utils::{OutputConfig, StructTable},
};

const TITLE: &str = "Identity Projects";

#[derive(Deserialize, StructTable)]
pub struct ProjectData {
#[structable(title = "Name")]
name: String,
#[structable(title = "ID")]
id: String,
#[structable(title = "Parent ID")]
parent_id: String,
#[structable(title = "Enabled")]
enabled: bool,
}

pub type IdentityProjects<'a> = TableViewComponentBase<'a, ProjectData, IdentityProjectFilters>;

impl<'a> Component for IdentityProjects<'a> {
fn register_config_handler(&mut self, config: Config) -> Result<()> {
self.set_config(config)?;
Ok(())
}

fn register_action_handler(&mut self, tx: UnboundedSender<Action>) -> Result<()> {
self.set_command_tx(tx);
Ok(())
}

fn update(&mut self, action: Action, current_mode: Mode) -> Result<Option<Action>> {
match action {
Action::CloudChangeScope(_) => {
self.set_loading(true);
}
Action::ConnectedToCloud(_) => {
self.set_loading(true);
self.set_data(Vec::new())?;
if let Mode::IdentityProjects = current_mode {
return Ok(Some(Action::RequestCloudResource(
Resource::IdentityProjects(self.get_filters().clone()),
)));
}
}
Action::Mode(Mode::IdentityProjects) | Action::Refresh => {
self.set_loading(true);
return Ok(Some(Action::RequestCloudResource(
Resource::IdentityProjects(self.get_filters().clone()),
)));
}
Action::Tick => {
self.app_tick()?;
if let Mode::IdentityProjects = current_mode {
return Ok(Some(Action::RequestCloudResource(
Resource::IdentityProjects(self.get_filters().clone()),
)));
}
}
Action::Render => self.render_tick()?,
Action::ResourcesData {
resource: Resource::IdentityProjects(_),
data,
} => {
self.set_data(data)?;
}
_ => {}
};
Ok(None)
}

fn handle_key_events(&mut self, key: KeyEvent) -> Result<Option<Action>> {
match key.code {
KeyCode::Down => self.cursor_down()?,
KeyCode::Up => self.cursor_up()?,
KeyCode::Home => self.cursor_first()?,
KeyCode::End => self.cursor_last()?,
KeyCode::PageUp => self.cursor_page_up()?,
KeyCode::PageDown => self.cursor_page_down()?,
KeyCode::Left => self.cursor_left()?,
KeyCode::Right => self.cursor_right()?,
KeyCode::Tab => self.key_tab()?,
_ => {}
}
if key.kind == KeyEventKind::Press && key.code == KeyCode::Enter {
if let Some(x) = self.get_selected_raw() {
return Ok(Some(Action::Describe(x.clone())));
}
}
Ok(None)
}

fn draw(&mut self, f: &mut Frame<'_>, area: Rect) -> Result<()> {
let areas = Layout::vertical([Constraint::Min(5), Constraint::Length(3)]).split(area);

self.render_content(TITLE, f, areas[0])?;
self.render_footer(f, areas[1]);
Ok(())
}
}
4 changes: 4 additions & 0 deletions openstack_tui/src/components/resource_select_popup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ impl ResourceSelect {
("Servers", Mode::ComputeServers),
]),
),
(
"Identity",
HashMap::from([("Projects", Mode::IdentityProjects)]),
),
("Image", HashMap::from([("Images", Mode::ImageImages)])),
(
"Network",
Expand Down
1 change: 1 addition & 0 deletions openstack_tui/src/mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub enum Mode {
Describe,
ComputeFlavors,
ComputeServers,
IdentityProjects,
ImageImages,
NetworkNetworks,
NetworkSubnets,
Expand Down