Skip to content

Commit

Permalink
Change defaults object from table to userdata
Browse files Browse the repository at this point in the history
  • Loading branch information
hahnavi committed Dec 25, 2024
1 parent 7c98dff commit 3120a9c
Show file tree
Hide file tree
Showing 11 changed files with 1,010 additions and 260 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
- name: Generate coverage report
run: |
cargo +nightly tarpaulin --verbose --out Xml --implicit-test-threads
cargo +nightly tarpaulin --verbose --out Xml --implicit-test-threads --workspace
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v5
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,4 @@ jobs:
echo "127.0.0.1 localhost2" | sudo tee -a /etc/hosts > /dev/null
- name: Run tests
run: cargo test --verbose
run: cargo test --verbose --workspace
27 changes: 25 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,11 +139,34 @@ For detailed explanations, arguments, and examples of each module, please refer
Komandan offers built-in functions to enhance scripting capabilities:

- **`komandan.filter_hosts`**: Filters a list of hosts based on a pattern.
- **`komandan.parse_hosts_json`**: Parses a JSON file containing hosts information.
- **`komandan.set_defaults`**: Sets default values for host connection parameters.
- **`komandan.parse_hosts_json_file`**: Parses a JSON file containing hosts information.
- **`komandan.parse_hosts_json_url`**: Parses a JSON file from a URL containing hosts information.

For detailed descriptions and usage examples of these functions, please visit the [Built-in Functions section of the Komandan Documentation Site](https://komandan.vercel.app/docs/functions/).

## Default Values

Komandan provides default values for various parameters, such as the user, private key file path, and SSH port. These values can be set using the `komandan.defaults` userdata.

```lua
-- set default values
komandan.defaults:set_port(22)
komandan.defaults:set_user("user1")
komandan.defaults:set_private_key_file(os.getenv("HOME") .. "/.ssh/id_ed25519")
komandan.defaults:set_private_key_pass("passphrase")
komandan.defaults:set_host_key_check(false)
komandan.defaults:set_env("ENV_VAR", "value")

-- get default values
local port = komandan.defaults:get_port()
local user = komandan.defaults:get_user()
local private_key_file = komandan.defaults:get_private_key_file()
local private_key_pass = komandan.defaults:get_private_key_pass()
local host_key_check = komandan.defaults:get_host_key_check()
local env = komandan.defaults:get_env("ENV_VAR")
local env_all = komandan.defaults:get_all_env()
```

## Error Handling

Komandan provides error information through the return values of the `komando` function. If a task fails, the `exit_code` will be non-zero, and `stderr` may contain error messages. You can use the `ignore_exit_code` option in a task to continue execution even if a task fails.
Expand Down
6 changes: 2 additions & 4 deletions examples/multi_hosts_tasks.lua
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
local hosts = require("hosts")

komandan.set_defaults({
user = "user1",
private_key_file = os.getenv("HOME") .. "/.ssh/id_ed25519",
})
komandan.defaults:set_user("user1")
komandan.defaults:set_private_key_file(os.getenv("HOME") .. "/.ssh/id_ed25519")

local tasks = {
{
Expand Down
6 changes: 2 additions & 4 deletions examples/parse_hosts_json.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ local hosts = komandan.parse_hosts_json_file("/path/to/hosts.json")
-- or use a URL
-- local hosts = komandan.parse_hosts_json_url("http://localhost:8000/hosts.json")

komandan.set_defaults({
user = "user1",
private_key_file = os.getenv("HOME") .. "/.ssh/id_ed25519",
})
komandan.defaults:set_user("user1")
komandan.defaults:set_private_key_file(os.getenv("HOME") .. "/.ssh/id_ed25519")

for _, host in pairs(hosts) do
komandan.komando(host, {
Expand Down
187 changes: 187 additions & 0 deletions http-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -607,3 +607,190 @@ pub fn create_client_from_url(url: &str) -> Result<(HttpClient, String), Box<dyn

Ok((HttpClient::new(&base_url), full_path))
}

// Tests
#[cfg(test)]
mod tests {
use super::*;
use std::time::Duration;

#[test]
fn test_proxy_configuration() {
let mut client = HttpClient::new("http://example.com");
let proxy = ProxyConfig::new("proxy.example.com", 8080)
.with_auth("username", "password")
.with_https(false);

client.set_proxy(proxy.clone());

match &client.proxy {
Some(configured_proxy) => {
assert_eq!(configured_proxy.host, "proxy.example.com");
assert_eq!(configured_proxy.port, 8080);
assert_eq!(
configured_proxy.auth,
Some(("username".to_string(), "password".to_string()))
);
assert_eq!(configured_proxy.use_https, false);
}
None => panic!("Proxy should be configured"),
}
}

#[test]
fn test_http_method_to_string() {
assert_eq!(HttpMethod::GET.to_string(), "GET");
assert_eq!(HttpMethod::POST.to_string(), "POST");
assert_eq!(HttpMethod::PUT.to_string(), "PUT");
assert_eq!(HttpMethod::DELETE.to_string(), "DELETE");
assert_eq!(HttpMethod::PATCH.to_string(), "PATCH");
assert_eq!(HttpMethod::HEAD.to_string(), "HEAD");
assert_eq!(HttpMethod::CONNECT.to_string(), "CONNECT");
}

#[test]
fn test_http_client_initialization() {
let client = HttpClient::new("https://api.example.com");
assert_eq!(client.host, "https://api.example.com");
assert!(client.auth.is_none());
assert!(client.headers.is_empty());
assert!(client.timeout.is_none());
assert_eq!(client.max_redirects, 5);
assert!(client.proxy.is_none());
assert!(client.verify_ssl);
assert!(client.enable_ipv6);
}

#[test]
fn test_http_client_configuration() {
let mut client = HttpClient::new("https://api.example.com");

client.set_auth("username", "password");
assert_eq!(
client.auth,
Some(("username".to_string(), "password".to_string()))
);

client.set_header("User-Agent", "Test Client");
assert_eq!(
client.headers.get("User-Agent"),
Some(&"Test Client".to_string())
);

let timeout = Duration::from_secs(30);
client.set_timeout(timeout);
assert_eq!(client.timeout, Some(timeout));

client.set_max_redirects(3);
assert_eq!(client.max_redirects, 3);

client.set_verify_ssl(false);
assert!(!client.verify_ssl);

client.set_enable_ipv6(false);
assert!(!client.enable_ipv6);
}

#[test]
fn test_http_response_status_checks() {
let success_response = HttpResponse {
status_code: 200,
headers: HashMap::new(),
body: Vec::new(),
content_type: None,
};
assert!(success_response.is_success());
assert!(!success_response.is_error());

let client_error_response = HttpResponse {
status_code: 404,
headers: HashMap::new(),
body: Vec::new(),
content_type: None,
};
assert!(client_error_response.is_client_error());
assert!(client_error_response.is_error());

let server_error_response = HttpResponse {
status_code: 500,
headers: HashMap::new(),
body: Vec::new(),
content_type: None,
};
assert!(server_error_response.is_server_error());
assert!(server_error_response.is_error());
}

#[test]
fn test_parse_url() -> Result<(), Box<dyn Error>> {
let test_cases = vec![
("https://example.com/path?query=value", ParsedUrl {
scheme: "https".to_string(),
host: "example.com".to_string(),
path: "/path".to_string(),
query: Some("query=value".to_string()),
}),
("http://example.com", ParsedUrl {
scheme: "http".to_string(),
host: "example.com".to_string(),
path: "/".to_string(),
query: None,
}),
("https://api.example.com/v1/users/", ParsedUrl {
scheme: "https".to_string(),
host: "api.example.com".to_string(),
path: "/v1/users/".to_string(),
query: None,
}),
];

for (input, expected) in test_cases {
let parsed = parse_url(input)?;
assert_eq!(parsed.scheme, expected.scheme);
assert_eq!(parsed.host, expected.host);
assert_eq!(parsed.path, expected.path);
assert_eq!(parsed.query, expected.query);
}

Ok(())
}

#[test]
fn test_create_client_from_url() -> Result<(), Box<dyn Error>> {
let (client, path) =
create_client_from_url("https://api.example.com/v1/users?active=true")?;

assert_eq!(client.host, "https://api.example.com");
assert_eq!(path, "/v1/users?active=true");

let (client2, path2) = create_client_from_url("http://example.com")?;
assert_eq!(client2.host, "http://example.com");
assert_eq!(path2, "/");

Ok(())
}

#[test]
fn test_invalid_url() {
let result = parse_url("invalid-url");
assert!(result.is_err());

let result = create_client_from_url("invalid-url");
assert!(result.is_err());
}

#[test]
fn test_parse_response() {
let client = HttpClient::new("https://example.com");
let raw_response = "HTTP/1.1 200 OK\r\n\
Content-Type: application/json\r\n\
Content-Length: 2\r\n\
\r\n\
{}";

let response = client.parse_response(raw_response).unwrap();
assert_eq!(response.status_code, 200);
assert_eq!(response.content_type, Some("application/json".to_string()));
assert_eq!(response.body, "{}".as_bytes());
}
}
Loading

0 comments on commit 3120a9c

Please sign in to comment.