/ README.md
README.md
  1  # Backstage Client Library
  2  
  3  The `backstage-client` library is a Rust-based client for interacting with the Backstage API. It allows you to retrieve various entities from the Backstage API catalog, including components, APIs, resources, systems, groups, locations, domains, and templates.
  4  
  5  ## Features
  6  
  7  - **Retrieve Entities**: Fetch different types of entities from the Backstage API catalog.
  8  - **Filter Support**: Use filters to retrieve specific kinds of entities.
  9  
 10  ## Supported Entity Kinds
 11  
 12  The library supports the following entity kinds:
 13  
 14  - **Component**: Represents a component in the Backstage catalog.
 15  - **API**: Represents an API in the Backstage catalog.
 16  - **Resource**: Represents a resource in the Backstage catalog.
 17  - **System**: Represents a system in the Backstage catalog.
 18  - **Group**: Represents a group in the Backstage catalog.
 19  - **Location**: Represents a location in the Backstage catalog.
 20  - **Domain**: Represents a domain in the Backstage catalog.
 21  - **Template**: Represents a template in the Backstage catalog.
 22  
 23  ## Installation
 24  
 25  Add the `backstage-client` crate to your `Cargo.toml` file:
 26  
 27  ```toml
 28  [dependencies]
 29  backstage-client = "0.1.2"  # Replace with the latest version
 30  tokio = { version = "1", features = ["full"] }
 31  log = "0.4"
 32  env_logger = "0.10"
 33  ```
 34  
 35  ## Usage
 36  ### Example 1: Fetching all Entities
 37  
 38  Here's an example of how to use the backstage-client library to fetch all entities from the Backstage API catalog:
 39  
 40  ```rs
 41  use backstage_client::{BackstageClient, entities::Entity, ClientError};
 42  use log::{info, error};
 43  use std::env;
 44  
 45  #[tokio::main]
 46  async fn main() -> Result<(), Box<dyn std::error::Error>> {
 47      // Initialize logging
 48      env_logger::init();
 49  
 50      // Get configuration from environment variables
 51      let base_url = env::var("BACKSTAGE_URL")
 52          .unwrap_or_else(|_| "https://backstage.example.com".to_string());
 53      let token = env::var("BACKSTAGE_TOKEN")
 54          .expect("BACKSTAGE_TOKEN environment variable must be set");
 55  
 56      // Create a new Backstage client
 57      let client = BackstageClient::new(&base_url, &token)?;
 58  
 59      // Fetch entities without filters
 60      match client.fetch_entities::<Entity>(None).await {
 61          Ok(entities) => {
 62              info!("Successfully fetched {} entities", entities.len());
 63              for entity in entities.iter().take(3) {
 64                  info!("Entity: {} ({})", entity.name(), entity.kind());
 65              }
 66          }
 67          Err(e) => {
 68              error!("Error fetching entities: {}", e);
 69              return Err(e.into());
 70          }
 71      }
 72  
 73      Ok(())
 74  }
 75  ```
 76  
 77  ### Example 2: Fetching Entities with Filters
 78  
 79  You can also use filters to retrieve specific kinds of entities. Here's an example of how to fetch `component`s of type `service`:
 80  
 81  ```rs
 82  use backstage_client::{BackstageClient, entities::Entity, ClientError};
 83  use log::{info, error};
 84  use std::{collections::HashMap, env};
 85  
 86  #[tokio::main]
 87  async fn main() -> Result<(), Box<dyn std::error::Error>> {
 88      // Initialize logging
 89      env_logger::init();
 90  
 91      // Get configuration from environment variables
 92      let base_url = env::var("BACKSTAGE_URL")
 93          .unwrap_or_else(|_| "https://backstage.example.com".to_string());
 94      let token = env::var("BACKSTAGE_TOKEN")
 95          .expect("BACKSTAGE_TOKEN environment variable must be set");
 96  
 97      // Create a new Backstage client
 98      let client = BackstageClient::new(&base_url, &token)?;
 99  
100      // Define filters to fetch components
101      let mut filters = HashMap::new();
102      filters.insert("kind".to_string(), "Component".to_string());
103      filters.insert("spec.type".to_string(), "service".to_string());
104  
105      // Fetch components with filters
106      match client.fetch_entities::<Entity>(Some(filters)).await {
107          Ok(components) => {
108              info!("Successfully fetched {} components", components.len());
109              for component in components.iter().take(5) {
110                  info!("Component: {} - {}", 
111                      component.name(), 
112                      component.description().unwrap_or("No description")
113                  );
114              }
115          }
116          Err(e) => {
117              error!("Error fetching components: {}", e);
118              return Err(e.into());
119          }
120      }
121  
122      Ok(())
123  }
124  ```
125  
126  ### Example 3: Getting a Specific Entity
127  
128  You can retrieve a specific entity by its kind, namespace, and name:
129  
130  ```rs
131  use backstage_client::{BackstageClient, entities::Entity, ClientError};
132  use log::{info, error};
133  use std::env;
134  
135  #[tokio::main]
136  async fn main() -> Result<(), Box<dyn std::error::Error>> {
137      // Initialize logging
138      env_logger::init();
139  
140      // Get configuration from environment variables
141      let base_url = env::var("BACKSTAGE_URL")
142          .unwrap_or_else(|_| "https://backstage.example.com".to_string());
143      let token = env::var("BACKSTAGE_TOKEN")
144          .expect("BACKSTAGE_TOKEN environment variable must be set");
145  
146      // Create a new Backstage client
147      let client = BackstageClient::new(&base_url, &token)?;
148  
149      // Get a specific component by name
150      match client.get_entity::<Entity>("Component", Some("default"), "my-service").await {
151          Ok(entity) => {
152              info!("Found entity: {}", entity);
153              info!("  Kind: {}", entity.kind());
154              info!("  Name: {}", entity.name());
155              info!("  Namespace: {}", entity.namespace());
156              if let Some(description) = entity.description() {
157                  info!("  Description: {}", description);
158              }
159          }
160          Err(e) => {
161              error!("Error fetching entity: {}", e);
162              return Err(e.into());
163          }
164      }
165  
166      Ok(())
167  }
168  ```