Skip to content

Commit

Permalink
Add option to run enterprise edition (#15)
Browse files Browse the repository at this point in the history
* Add option to run enterprise edition

* Show full path in error message

* Update MSRV to 1.63.0

* Fix tests for latest neo4rs version

* Update doc test for new password method
  • Loading branch information
knutwalker committed Oct 6, 2023
1 parent f062360 commit f85e3b5
Show file tree
Hide file tree
Showing 8 changed files with 123 additions and 14 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ on:
env:
RUST_LOG: debug
CARGO_TERM_COLOR: always
MSRV: 1.60.0
MSRV: 1.63.0

jobs:
check:
Expand Down Expand Up @@ -74,7 +74,7 @@ jobs:
strategy:
fail-fast: false
matrix:
rust: [stable, beta, 1.60.0]
rust: [stable, beta, 1.63.0]
runs-on: ubuntu-latest
steps:
- name: Checkout code
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
Cargo.lock
.idea/

container-license-acceptance.txt
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ documentation = "https://docs.rs/neo4j_testcontainers"
readme = "README.md"
keywords = ["neo4j", "testcontainers", "docker"]
categories = ["development-tools::testing"]
rust-version = "1.60.0"
rust-version = "1.63.0"

[dependencies]
lenient_semver = { version = "0.4.2", default-features = false }
testcontainers = { version = "0.14.0" }

[dev-dependencies]
neo4rs = "0.6.0"
neo4rs = "0.6.2"
tokio = { version = "1.28.2", features = ["test-util", "macros"] }
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# neo4j_testcontainers [![CI Status][ci-badge]][ci-url] [![Crates.io][crates-badge]][crates-url] [![Docs][docs-badge]][docs-url] ![License: MIT][license-badge] ![Rust Version: ^1.60.0][rust-version-badge]
# neo4j_testcontainers [![CI Status][ci-badge]][ci-url] [![Crates.io][crates-badge]][crates-url] [![Docs][docs-badge]][docs-url] ![License: MIT][license-badge] ![Rust Version: 1.63.0][rust-version-badge]

[ci-badge]: https://github.com/knutwalker/neo4j-testcontainers-rs/actions/workflows/checks.yml/badge.svg
[ci-url]: https://github.com/knutwalker/neo4j-testcontainers-rs
Expand All @@ -7,7 +7,7 @@
[docs-badge]: https://img.shields.io/badge/docs-latest-blue.svg?style=shield
[docs-url]: https://docs.rs/neo4j_testcontainers
[license-badge]: https://img.shields.io/badge/license-MIT-blue.svg?style=shield
[rust-version-badge]: https://img.shields.io/badge/rustc-%5E1.60.0-orange.svg?style=shield
[rust-version-badge]: https://img.shields.io/badge/rustc-1.63.0-orange.svg?style=shield

Neo4j image for [testcontainers][__link0].

Expand Down Expand Up @@ -62,7 +62,7 @@ Supported plugins are APOC, APOC Core, Bloom, Streams, Graph Data Science, and N

## MSRV

The crate has a minimum supported Rust version (MSRV) of `1.60.0`.
The crate has a minimum supported Rust version (MSRV) of `1.63.0`.

A change in the MSRV in *not* considered a breaking change. For versions past 1.0.0, a change in the MSRV can be done in a minor version increment (1.1.3 -> 1.2.0) for versions before 1.0.0, a change in the MSRV can be done in a patch version increment (0.1.3 -> 0.1.4).

Expand Down
4 changes: 2 additions & 2 deletions doc/lib.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ let docker = Cli::default();
let container = docker.run(Neo4j::default());
let uri = container.image().bolt_uri_ipv4();
let auth_user = container.image().user();
let auth_pass = container.image().pass();
let auth_pass = container.image().password();
// connect to Neo4j with the uri, user and pass
```

Expand Down Expand Up @@ -49,7 +49,7 @@ Supported plugins are APOC, APOC Core, Bloom, Streams, Graph Data Science, and N

# MSRV

The crate has a minimum supported Rust version (MSRV) of `1.60.0`.
The crate has a minimum supported Rust version (MSRV) of `1.63.0`.

A change in the MSRV in *not* considered a breaking change.
For versions past 1.0.0, a change in the MSRV can be done in a minor version increment (1.1.3 -> 1.2.0)
Expand Down
73 changes: 69 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
while_true
)]

use std::{borrow::Cow, cell::RefCell, collections::HashMap};
use std::{borrow::Cow, cell::RefCell, collections::HashMap, io::BufRead};
use testcontainers::{
core::{ContainerState, WaitFor},
Container, Image, RunnableImage,
Expand Down Expand Up @@ -74,6 +74,7 @@ pub struct Neo4j {
version: Value,
user: Value,
pass: Value,
enterprise: bool,
plugins: Vec<Neo4jLabsPlugin>,
}

Expand All @@ -89,6 +90,7 @@ impl Neo4j {
version: Value::Default(Self::DEFAULT_VERSION_TAG),
user: Value::Default(Self::DEFAULT_USER),
pass: Value::Default(Self::DEFAULT_PASS),
enterprise: false,
plugins: Vec::new(),
}
}
Expand All @@ -109,6 +111,7 @@ impl Neo4j {
var: "NEO4J_TEST_PASS",
fallback: Self::DEFAULT_PASS,
},
enterprise: false,
plugins: Vec::new(),
}
}
Expand Down Expand Up @@ -165,6 +168,50 @@ impl Neo4j {
self
}

/// Use the enterprise edition of Neo4j.
///
/// # Note
/// Please have a look at the [Neo4j Licensing page](https://neo4j.com/licensing/).
/// While the Neo4j Community Edition can be used for free in your projects under the GPL v3 license,
/// Neo4j Enterprise edition needs either a commercial, education or evaluation license.
pub fn with_enterprise_edition(
mut self,
) -> Result<Self, Box<dyn std::error::Error + Sync + Send + 'static>> {
const ACCEPTANCE_FILE_NAME: &str = "container-license-acceptance.txt";

let version = Self::value(&self.version).expect("Version is always set");
let image = format!("neo4j:{}-enterprise", version);

let acceptance_file = std::env::current_dir()
.ok()
.map(|o| o.join(ACCEPTANCE_FILE_NAME));

let has_license_acceptance = acceptance_file
.as_deref()
.and_then(|o| std::fs::File::open(o).ok())
.into_iter()
.flat_map(|o| std::io::BufReader::new(o).lines())
.any(|o| o.map_or(false, |line| line.trim() == image));

if !has_license_acceptance {
return Err(format!(
concat!(
"You need to accept the Neo4j Enterprise Edition license by ",
"creating the file `{}` with the following content:\n\n\t{}",
),
acceptance_file.map_or_else(
|| ACCEPTANCE_FILE_NAME.to_owned(),
|o| { o.display().to_string() }
),
image
)
.into());
}

self.enterprise = true;
Ok(self)
}

/// Add Neo4j lab plugins to get started with the database.
#[must_use]
pub fn with_neo4j_labs_plugin(mut self, plugins: &[Neo4jLabsPlugin]) -> Self {
Expand Down Expand Up @@ -381,6 +428,15 @@ impl Image for Neo4jImage {
}

impl Neo4j {
fn enterprise_env(&self) -> impl IntoIterator<Item = (String, String)> {
self.enterprise.then(|| {
(
"NEO4J_ACCEPT_LICENSE_AGREEMENT".to_owned(),
"yes".to_owned(),
)
})
}

fn auth_env(&self) -> impl IntoIterator<Item = (String, String)> {
fn auth(image: &Neo4j) -> Option<String> {
let user = Neo4j::value(&image.user)?;
Expand Down Expand Up @@ -428,6 +484,10 @@ impl Neo4j {

let mut env_vars = HashMap::new();

for (key, value) in self.enterprise_env() {
env_vars.insert(key, value);
}

for (key, value) in self.auth_env() {
env_vars.insert(key, value);
}
Expand All @@ -444,10 +504,15 @@ impl Neo4j {
Self::value(&self.pass).map(|pass| (user.into_owned(), pass.into_owned()))
});

let version = Self::value(&self.version).expect("Version must be set");
let version = format!(
"{}{}",
version,
if self.enterprise { "-enterprise" } else { "" }
);

Neo4jImage {
version: Self::value(&self.version)
.expect("Version must be set")
.into_owned(),
version,
auth,
env_vars,
state: RefCell::new(None),
Expand Down
44 changes: 44 additions & 0 deletions tests/enterprise.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use neo4j_testcontainers::Neo4j;
use neo4rs::Graph;
use testcontainers::clients::Cli;

#[tokio::test]
async fn runs_enterprise() {
let neo4j = match Neo4j::default().with_enterprise_edition() {
Ok(n) => n,
Err(e) => {
eprintln!(
"Skipping enterprise test, no license acceptance file found: {}",
e
);
return;
}
}
.with_password("Picard123");

let docker = Cli::default();
let container = docker.run(neo4j);

let image = container.image();

let uri = image.bolt_uri_ipv4();
assert!(uri.starts_with("bolt://"));

let uri = image.http_uri_ipv4();
assert!(uri.starts_with("http://"));

let uri = image.bolt_uri_ipv4();
let auth_user = image.user().expect("default user");
let auth_pass = image.password().expect("set password");

let graph = Graph::new(uri, auth_user, auth_pass).await.unwrap();
let mut result = graph
.execute(neo4rs::query(
"CALL dbms.components() YIELD edition RETURN edition",
))
.await
.unwrap();
let row = result.next().await.unwrap().unwrap();
let value: String = row.get("edition").unwrap();
assert_eq!(value, "enterprise");
}
1 change: 0 additions & 1 deletion tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ async fn it_works() {
assert!(uri.starts_with("http://"));

let uri = container.image().bolt_uri_ipv4();
let uri = uri.trim_start_matches("bolt://");
let auth_user = container.image().user().expect("default user");
let auth_pass = container.image().password().expect("default password");

Expand Down

0 comments on commit f85e3b5

Please sign in to comment.