Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
1 change: 1 addition & 0 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ jobs:
run: ls -R .
shell: bash
- name: Test bindings
if: runner.os != 'Windows'
run: yarn test
test-linux-binding:
name: Test ${{ matrix.target }} - node@${{ matrix.node }}
Expand Down
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ crate-type = ["cdylib"]

[dependencies]
anyhow = "1.0.99"
atlas-local = { git = "https://github.com/mongodb/atlas-local-lib.git", rev = "36f56065e891bbe045beeb46489dd7d4142dbd41" }
atlas-local = { git = "https://github.com/mongodb/atlas-local-lib.git", rev = "323a879b8385e8e572f8545e3273fafa5698f8c6" }
bollard = "0.19.2"
napi = { version = "3.0.0", features = ["async", "anyhow"] }
napi-derive = "3.0.0"
semver = "1.0.26"

[build-dependencies]
napi-build = "2"
Expand Down
25 changes: 16 additions & 9 deletions __test__/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,23 @@ test('smoke test', async (t) => {
return
}

// TODO: Implement once createDeployment is added
// let deploymentName = "test_deployment"
// await client.createDeployment(...)
// Count initial deployments
let start_deployments_count = (await client.listDeployments()).length

// List deployments
// We don't care about the number, we're just testing that the method doesn't fail
await client.listDeployments()
// Create deployment
let createDeploymentOptions = {
name: "test_deployment",
}
await client.createDeployment(createDeploymentOptions)

// Count deployments after creation
let after_create_deployment_count = (await client.listDeployments()).length
t.assert(after_create_deployment_count - start_deployments_count === 1)

// TODO: Uncommment when createDeployment is added
// await client.deleteDeployment(deploymentName)
// Delete deployment
await client.deleteDeployment(createDeploymentOptions.name)

t.pass()
// Count deployments after deletion
let after_delete_deployment_count = (await client.listDeployments()).length
t.assert(start_deployments_count === after_delete_deployment_count)
})
21 changes: 20 additions & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
/* eslint-disable */
export declare class Client {
static connect(): Client
createDeployment(createDeplomentOptions: CreateDeploymentOptions): Promise<void>
listDeployments(): Promise<Array<Deployment>>
deleteDeployment(deploymentName: string): Promise<void>
}
Expand All @@ -12,6 +13,24 @@ export declare const enum BindingType {
Specific = 'Specific'
}

export interface CreateDeploymentOptions {
name?: string
image?: string
mongodbVersion?: string
creationSource?: CreationSource
localSeedLocation?: string
mongodbInitdbDatabase?: string
mongodbInitdbRootPasswordFile?: string
mongodbInitdbRootPassword?: string
mongodbInitdbRootUsernameFile?: string
mongodbInitdbRootUsername?: string
mongotLogFile?: string
runnerLogFile?: string
doNotTrack?: boolean
telemetryBaseUrl?: string
mongodbPortBinding?: MongoDBPortBinding
}

export interface CreationSource {
type: CreationSourceType
source: string
Expand All @@ -20,7 +39,7 @@ export interface CreationSource {
export declare const enum CreationSourceType {
AtlasCLI = 'AtlasCLI',
Container = 'Container',
MCP = 'MCP',
MCPServer = 'MCPServer',
Other = 'Other'
}

Expand Down
13 changes: 13 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,19 @@ impl Client {
})
}

#[napi]
pub async fn create_deployment(
&self,
create_deploment_options: crate::models::create_deployment::CreateDeploymentOptions,
) -> Result<()> {
let options: atlas_local::models::CreateDeploymentOptions = create_deploment_options.into();
self
.client
.create_deployment(&options)
.await
.context("create deployment")
}

#[napi]
pub async fn list_deployments(&self) -> Result<Vec<Deployment>> {
self
Expand Down
160 changes: 160 additions & 0 deletions src/models/create_deployment.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
use crate::models::list_deployments::{CreationSource, MongoDBPortBinding};
use napi_derive::napi;
use semver::Version;

#[napi(object)]
pub struct CreateDeploymentOptions {
// Identifiers
pub name: Option<String>,

// Image details
pub image: Option<String>,
pub mongodb_version: Option<String>,

// Creation source
pub creation_source: Option<CreationSource>,

// Initial database configuration
pub local_seed_location: Option<String>,
pub mongodb_initdb_database: Option<String>,
pub mongodb_initdb_root_password_file: Option<String>,
pub mongodb_initdb_root_password: Option<String>,
pub mongodb_initdb_root_username_file: Option<String>,
pub mongodb_initdb_root_username: Option<String>,

// Logging
pub mongot_log_file: Option<String>,
pub runner_log_file: Option<String>,

// Telemetry
pub do_not_track: Option<bool>,
pub telemetry_base_url: Option<String>,

// Port configuration
pub mongodb_port_binding: Option<MongoDBPortBinding>,
}

impl From<CreateDeploymentOptions> for atlas_local::models::CreateDeploymentOptions {
fn from(source: CreateDeploymentOptions) -> Self {
let version: Option<Version> = match source.mongodb_version.as_deref() {
Some("latest") => None,
None => None,
Some(ver_string) => {
// If malformed Version if given, it will panic here
Some(Version::parse(ver_string).expect("Parse version string"))
}
};

Self {
name: source.name,
image: source.image,
mongodb_version: version,
creation_source: source
.creation_source
.map(atlas_local::models::CreationSource::from),
local_seed_location: source.local_seed_location,
mongodb_initdb_database: source.mongodb_initdb_database,
mongodb_initdb_root_password_file: source.mongodb_initdb_root_password_file,
mongodb_initdb_root_password: source.mongodb_initdb_root_password,
mongodb_initdb_root_username_file: source.mongodb_initdb_root_username_file,
mongodb_initdb_root_username: source.mongodb_initdb_root_username,
mongot_log_file: source.mongot_log_file,
runner_log_file: source.runner_log_file,
do_not_track: source.do_not_track,
telemetry_base_url: source.telemetry_base_url,
mongodb_port_binding: source
.mongodb_port_binding
.map(atlas_local::models::MongoDBPortBinding::from),
}
}
}

#[cfg(test)]
mod tests {
use crate::models::list_deployments::{BindingType, CreationSourceType};

use super::*;

#[test]
fn test_lib_create_deployment_options_from_create_deployment_options() {
let create_deployment_options = CreateDeploymentOptions {
name: Some("test_deployment".to_string()),
image: Some("mongodb/mongodb-atlas-local".to_string()),
mongodb_version: Some("8.0.0".to_string()),
creation_source: Some(CreationSource {
source_type: CreationSourceType::MCPServer,
source: "MCPSERVER".to_string(),
}),
local_seed_location: Some("/host/seed-data".to_string()),
mongodb_initdb_database: Some("testdb".to_string()),
mongodb_initdb_root_password_file: Some("/run/secrets/password".to_string()),
mongodb_initdb_root_password: Some("password123".to_string()),
mongodb_initdb_root_username_file: Some("/run/secrets/username".to_string()),
mongodb_initdb_root_username: Some("admin".to_string()),
mongot_log_file: Some("/tmp/mongot.log".to_string()),
runner_log_file: Some("/tmp/runner.log".to_string()),
do_not_track: Some(false),
telemetry_base_url: Some("https://telemetry.example.com".to_string()),
mongodb_port_binding: Some(MongoDBPortBinding {
binding_type: BindingType::Loopback,
ip: "127.0.0.1".to_string(),
port: 27017,
}),
};
let lib_create_deployment_options: atlas_local::models::CreateDeploymentOptions =
create_deployment_options.into();
assert_eq!(
lib_create_deployment_options.name,
Some("test_deployment".to_string())
);
assert_eq!(
lib_create_deployment_options.image,
Some("mongodb/mongodb-atlas-local".to_string())
);
assert_eq!(
lib_create_deployment_options.mongodb_version,
Some(Version::new(8, 0, 0))
);
assert_eq!(
lib_create_deployment_options.creation_source,
Some(atlas_local::models::CreationSource::MCPServer)
);
assert_eq!(
lib_create_deployment_options.local_seed_location,
Some("/host/seed-data".to_string())
);
assert_eq!(
lib_create_deployment_options.mongodb_initdb_database,
Some("testdb".to_string())
);
assert_eq!(
lib_create_deployment_options.mongodb_initdb_root_password_file,
Some("/run/secrets/password".to_string())
);
assert_eq!(
lib_create_deployment_options.mongodb_initdb_root_password,
Some("password123".to_string())
);
assert_eq!(
lib_create_deployment_options.mongodb_initdb_root_username_file,
Some("/run/secrets/username".to_string())
);
assert_eq!(
lib_create_deployment_options.mongodb_initdb_root_username,
Some("admin".to_string())
);
assert_eq!(
lib_create_deployment_options.mongot_log_file,
Some("/tmp/mongot.log".to_string())
);
assert_eq!(
lib_create_deployment_options.runner_log_file,
Some("/tmp/runner.log".to_string())
);
assert_eq!(lib_create_deployment_options.do_not_track, Some(false));
assert_eq!(
lib_create_deployment_options.telemetry_base_url,
Some("https://telemetry.example.com".to_string())
);
}
}
Loading
Loading