Page MenuHomeDevCentral

D1868.diff
No OneTemporary

D1868.diff

diff --git a/Cargo.toml b/Cargo.toml
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -7,5 +7,9 @@
[dependencies]
env_logger = "^0.5.13"
limiting-factor = { path = "../limiting-factor", features = ["minimal"] }
+log = "^0.4.5"
rocket = "^0.3.16"
rocket_codegen = "^0.3.16"
+rocket_contrib = { version = "*", features = ["json"] }
+serde = "1.0"
+serde_derive = "1.0"
diff --git a/src/app.rs b/src/app.rs
--- a/src/app.rs
+++ b/src/app.rs
@@ -8,6 +8,7 @@
let routes = routes![
status,
favicon,
+ get_registry_stats,
];
MinimalApplication::start_application(routes);
diff --git a/src/lib.rs b/src/lib.rs
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,5 +1,11 @@
#![feature(plugin)]
#![plugin(rocket_codegen)]
+#[macro_use]
+extern crate log;
+
+extern crate rocket_contrib;
+
pub mod app;
+pub mod registry;
pub mod requests;
diff --git a/src/registry.rs b/src/registry.rs
new file mode 100644
--- /dev/null
+++ b/src/registry.rs
@@ -0,0 +1,83 @@
+use serde_derive::{Deserialize, Serialize};
+use std::fs::{DirEntry, read_dir};
+use std::io::Result as IOResult;
+use std::path::Path;
+
+/* -------------------------------------------------------------
+ Registry
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+/// Represents a Docker registry
+#[serde(rename_all = "camelCase")]
+#[derive(Serialize, Deserialize)]
+pub struct Registry {
+ #[serde(skip_serializing)]
+ pub directory: String,
+
+ pub repositories_count: i32
+}
+
+impl Registry {
+ const DEFAULT_LOCATION: &'static str = "/var/lib/registry";
+
+ pub fn new (directory: String) -> Self {
+ let mut registry = Registry {
+ directory,
+ repositories_count: 0,
+ };
+
+ registry.update_stats();
+
+ registry
+ }
+
+ pub fn with_default_location () -> Self {
+ Self::new(String::from(Self::DEFAULT_LOCATION))
+ }
+
+ pub fn update_stats (&mut self) {
+ self.repositories_count = self.count_repositories();
+ }
+
+ pub fn count_repositories (&self) -> i32 {
+ let path_name = format!("{}/docker/registry/v2/repositories", self.directory);
+ let path = Path::new(&path_name);
+
+ if path.exists() && path.is_dir() {
+ match count_subdirectories(path) {
+ Ok(n) => n as i32,
+ Err(e) => {
+ error!(target: "api", "Can't count registry directories: {}", e);
+
+ 0
+ }
+ }
+ } else {
+ error!(target: "api",
+ "Registry path doesn't exist or isn't a directory: {}",
+ path_name);
+
+ 0
+ }
+ }
+}
+
+
+/* -------------------------------------------------------------
+ File system helper functions
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+fn count_subdirectories (dir: &Path) -> IOResult<usize> {
+ let count = read_dir(dir)?
+ .filter(|entry| is_entry_sub_directory(entry))
+ .count();
+
+ Ok(count)
+}
+
+fn is_entry_sub_directory(entry: &IOResult<DirEntry>) -> bool {
+ match entry {
+ Ok(e) => e.path().is_dir(),
+ Err(_) => false,
+ }
+}
diff --git a/src/requests.rs b/src/requests.rs
--- a/src/requests.rs
+++ b/src/requests.rs
@@ -2,6 +2,8 @@
//! Requests handled by the microservice.
//!
+use crate::registry::Registry;
+use limiting_factor::api::replies::{ApiJsonResponse, ApiResponse};
use rocket::response::NamedFile;
#[get("/status")]
@@ -13,3 +15,13 @@
pub fn favicon() -> Option<NamedFile> {
NamedFile::open("assets/favicon.ico").ok()
}
+
+// -------------------------------------------------------------
+// /registry
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+#[get("/registry/stats")]
+pub fn get_registry_stats() -> ApiJsonResponse<Registry> {
+ Registry::with_default_location()
+ .into_json_response()
+}
diff --git a/tests/broken-registry b/tests/broken-registry
new file mode 100644
diff --git a/tests/lib.rs b/tests/lib.rs
new file mode 100644
--- /dev/null
+++ b/tests/lib.rs
@@ -0,0 +1,22 @@
+use docker_registry_api::registry::Registry;
+
+#[test]
+fn test_registry_stats() {
+ let registry = Registry::new("tests/registry".to_string());
+
+ assert_eq!(3, registry.count_repositories()); // Lorem, ipsum, dolor
+}
+
+#[test]
+fn test_registry_stats_when_registry_is_empty() {
+ let registry = Registry::new("tests/void-registry".to_string());
+
+ assert_eq!(0, registry.count_repositories());
+}
+
+#[test]
+fn test_registry_stats_when_registry_is_a_file() {
+ let registry = Registry::new("tests/broken-registry".to_string());
+
+ assert_eq!(0, registry.count_repositories());
+}

File Metadata

Mime Type
text/plain
Expires
Wed, Apr 9, 01:53 (16 h, 56 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2555287
Default Alt Text
D1868.diff (4 KB)

Event Timeline