diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index e083f2aa..b088d4cc 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -173,7 +173,7 @@ jobs: # uses: obi1kenobi/cargo-semver-checks-action@v2 uses: n0-computer/cargo-semver-checks-action@feat-baseline with: - package: iroh-n0des + package: iroh-services baseline-rev: ${{ env.HEAD_COMMIT_SHA }} use-cache: false @@ -208,7 +208,7 @@ jobs: - name: Install sccache uses: mozilla-actions/sccache-action@v0.0.9 - - name: iroh-n0des docs + - name: iroh-services docs run: cargo docs-rs clippy_check: diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index c73f6eac..424f2b88 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -29,45 +29,45 @@ jobs: PREVIEW_PATH: pr/${{ github.event.pull_request.number || inputs.pr_number }}/docs steps: - - uses: actions/checkout@v6 - - uses: dtolnay/rust-toolchain@master - with: - toolchain: nightly-2026-01-28 - - name: Install sccache - uses: mozilla-actions/sccache-action@v0.0.9 + - uses: actions/checkout@v6 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: nightly-2026-01-28 + - name: Install sccache + uses: mozilla-actions/sccache-action@v0.0.9 - - name: Generate Docs - run: cargo doc --workspace --all-features --no-deps - env: - RUSTDOCFLAGS: --cfg iroh_docsrs + - name: Generate Docs + run: cargo doc --workspace --all-features --no-deps + env: + RUSTDOCFLAGS: --cfg iroh_docsrs - - name: Deploy Docs to Preview Branch - uses: peaceiris/actions-gh-pages@v4 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: ./target/doc/ - destination_dir: ${{ env.PREVIEW_PATH }} - publish_branch: generated-docs-preview + - name: Deploy Docs to Preview Branch + uses: peaceiris/actions-gh-pages@v4 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./target/doc/ + destination_dir: ${{ env.PREVIEW_PATH }} + publish_branch: generated-docs-preview - - name: Find Docs Comment - uses: peter-evans/find-comment@v4 - id: fc - with: - issue-number: ${{ github.event.pull_request.number || inputs.pr_number }} - comment-author: 'github-actions[bot]' - body-includes: Documentation for this PR has been generated + - name: Find Docs Comment + uses: peter-evans/find-comment@v4 + id: fc + with: + issue-number: ${{ github.event.pull_request.number || inputs.pr_number }} + comment-author: "github-actions[bot]" + body-includes: Documentation for this PR has been generated - - name: Get current timestamp - id: get_timestamp - run: echo "TIMESTAMP=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_ENV + - name: Get current timestamp + id: get_timestamp + run: echo "TIMESTAMP=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_ENV - - name: Create or Update Docs Comment - uses: peter-evans/create-or-update-comment@v5 - with: - issue-number: ${{ github.event.pull_request.number || inputs.pr_number }} - comment-id: ${{ steps.fc.outputs.comment-id }} - body: | - Documentation for this PR has been generated and is available at: https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/${{ env.PREVIEW_PATH }}/iroh_n0des/ + - name: Create or Update Docs Comment + uses: peter-evans/create-or-update-comment@v5 + with: + issue-number: ${{ github.event.pull_request.number || inputs.pr_number }} + comment-id: ${{ steps.fc.outputs.comment-id }} + body: | + Documentation for this PR has been generated and is available at: https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/${{ env.PREVIEW_PATH }}/iroh_services/ - Last updated: ${{ env.TIMESTAMP }} - edit-mode: replace + Last updated: ${{ env.TIMESTAMP }} + edit-mode: replace diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 444f3fc7..571b1a28 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -6,15 +6,15 @@ on: workflow_call: inputs: rust-version: - description: 'The version of the rust compiler to run' + description: "The version of the rust compiler to run" type: string - default: 'stable' + default: "stable" flaky: - description: 'Whether to also run flaky tests' + description: "Whether to also run flaky tests" type: boolean default: false git-ref: - description: 'Which git ref to checkout' + description: "Which git ref to checkout" type: string default: ${{ github.ref }} @@ -23,7 +23,7 @@ env: RUSTFLAGS: -Dwarnings RUSTDOCFLAGS: -Dwarnings SCCACHE_CACHE_SIZE: "50G" - CRATES_LIST: "iroh-n0des" + CRATES_LIST: "iroh-services" IROH_FORCE_STAGING_RELAYS: "1" jobs: @@ -35,7 +35,7 @@ jobs: fail-fast: false matrix: name: [ubuntu-latest, macOS-arm-latest] - rust: [ '${{ inputs.rust-version }}' ] + rust: ["${{ inputs.rust-version }}"] features: [all, none, default] include: - name: ubuntu-latest @@ -53,91 +53,91 @@ jobs: # not SCCACHE_GHA_ENABLED. RUSTC_WRAPPER: "sccache" steps: - - name: Checkout - uses: actions/checkout@v6 - with: - ref: ${{ inputs.git-ref }} - - - name: Install ${{ matrix.rust }} rust - uses: dtolnay/rust-toolchain@master - with: - toolchain: ${{ matrix.rust }} - - - name: Install cargo-nextest - uses: taiki-e/install-action@v2 - with: - tool: nextest@0.9.80 - - - name: Install sccache - uses: mozilla-actions/sccache-action@v0.0.9 - - - name: Select features - run: | - case "${{ matrix.features }}" in - all) - echo "FEATURES=--all-features" >> "$GITHUB_ENV" - ;; - none) - echo "FEATURES=--no-default-features" >> "$GITHUB_ENV" - ;; - default) - echo "FEATURES=" >> "$GITHUB_ENV" - ;; - *) - exit 1 - esac - - - name: check features - if: ${{ ! inputs.flaky }} - run: | - for i in ${CRATES_LIST//,/ } - do - echo "Checking $i $FEATURES" - if [ $i = "iroh-cli" ]; then - targets="--bins" + - name: Checkout + uses: actions/checkout@v6 + with: + ref: ${{ inputs.git-ref }} + + - name: Install ${{ matrix.rust }} rust + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.rust }} + + - name: Install cargo-nextest + uses: taiki-e/install-action@v2 + with: + tool: nextest@0.9.80 + + - name: Install sccache + uses: mozilla-actions/sccache-action@v0.0.9 + + - name: Select features + run: | + case "${{ matrix.features }}" in + all) + echo "FEATURES=--all-features" >> "$GITHUB_ENV" + ;; + none) + echo "FEATURES=--no-default-features" >> "$GITHUB_ENV" + ;; + default) + echo "FEATURES=" >> "$GITHUB_ENV" + ;; + *) + exit 1 + esac + + - name: check features + if: ${{ ! inputs.flaky }} + run: | + for i in ${CRATES_LIST//,/ } + do + echo "Checking $i $FEATURES" + if [ $i = "iroh-cli" ]; then + targets="--bins" + else + targets="--lib --bins" + fi + echo cargo check -p $i $FEATURES $targets + cargo check -p $i $FEATURES $targets + done + env: + RUST_LOG: ${{ runner.debug && 'TRACE' || 'DEBUG'}} + + - name: build tests + run: | + cargo nextest run --workspace ${{ env.FEATURES }} --lib --bins --tests --no-run + + - name: list ignored tests + run: | + cargo nextest list --workspace ${{ env.FEATURES }} --lib --bins --tests --run-ignored ignored-only + + - name: run tests + run: | + mkdir -p output + cargo nextest run --workspace ${{ env.FEATURES }} --lib --bins --tests --profile ci --run-ignored ${{ inputs.flaky && 'all' || 'default' }} --no-fail-fast --message-format ${{ inputs.flaky && 'libtest-json' || 'human' }} > output/${{ matrix.name }}_${{ matrix.features }}_${{ matrix.rust }}.json + env: + RUST_LOG: ${{ runner.debug && 'TRACE' || 'DEBUG'}} + NEXTEST_EXPERIMENTAL_LIBTEST_JSON: 1 + + - name: upload results + if: ${{ failure() && inputs.flaky }} + uses: actions/upload-artifact@v6 + with: + name: libtest_run_${{ github.run_number }}-${{ github.run_attempt }}-${{ matrix.name }}_${{ matrix.features }}_${{ matrix.rust }}.json + path: output + retention-days: 45 + compression-level: 0 + + - name: doctests + if: ${{ (! inputs.flaky) && matrix.features == 'all' }} + run: | + if [ -n "${{ runner.debug }}" ]; then + export RUST_LOG=TRACE else - targets="--lib --bins" + export RUST_LOG=DEBUG fi - echo cargo check -p $i $FEATURES $targets - cargo check -p $i $FEATURES $targets - done - env: - RUST_LOG: ${{ runner.debug && 'TRACE' || 'DEBUG'}} - - - name: build tests - run: | - cargo nextest run --workspace ${{ env.FEATURES }} --lib --bins --tests --no-run - - - name: list ignored tests - run: | - cargo nextest list --workspace ${{ env.FEATURES }} --lib --bins --tests --run-ignored ignored-only - - - name: run tests - run: | - mkdir -p output - cargo nextest run --workspace ${{ env.FEATURES }} --lib --bins --tests --profile ci --run-ignored ${{ inputs.flaky && 'all' || 'default' }} --no-fail-fast --message-format ${{ inputs.flaky && 'libtest-json' || 'human' }} > output/${{ matrix.name }}_${{ matrix.features }}_${{ matrix.rust }}.json - env: - RUST_LOG: ${{ runner.debug && 'TRACE' || 'DEBUG'}} - NEXTEST_EXPERIMENTAL_LIBTEST_JSON: 1 - - - name: upload results - if: ${{ failure() && inputs.flaky }} - uses: actions/upload-artifact@v6 - with: - name: libtest_run_${{ github.run_number }}-${{ github.run_attempt }}-${{ matrix.name }}_${{ matrix.features }}_${{ matrix.rust }}.json - path: output - retention-days: 45 - compression-level: 0 - - - name: doctests - if: ${{ (! inputs.flaky) && matrix.features == 'all' }} - run: | - if [ -n "${{ runner.debug }}" ]; then - export RUST_LOG=TRACE - else - export RUST_LOG=DEBUG - fi - cargo test --workspace --all-features --doc + cargo test --workspace --all-features --doc build_and_test_windows: timeout-minutes: 30 @@ -147,7 +147,7 @@ jobs: fail-fast: false matrix: name: [windows-latest] - rust: [ '${{ inputs.rust-version}}' ] + rust: ["${{ inputs.rust-version}}"] features: [all, none, default] target: - x86_64-pc-windows-msvc @@ -160,70 +160,70 @@ jobs: # not SCCACHE_GHA_ENABLED. RUSTC_WRAPPER: "sccache" steps: - - name: Checkout - uses: actions/checkout@v6 - with: - ref: ${{ inputs.git-ref }} - - - name: Install ${{ matrix.rust }} - run: | - rustup toolchain install ${{ matrix.rust }} - rustup toolchain default ${{ matrix.rust }} - rustup target add ${{ matrix.target }} - rustup set default-host ${{ matrix.target }} - - - name: Install cargo-nextest - shell: powershell - run: | - $tmp = New-TemporaryFile | Rename-Item -NewName { $_ -replace 'tmp$', 'zip' } -PassThru - Invoke-WebRequest -OutFile $tmp https://get.nexte.st/latest/windows - $outputDir = if ($Env:CARGO_HOME) { Join-Path $Env:CARGO_HOME "bin" } else { "~/.cargo/bin" } - $tmp | Expand-Archive -DestinationPath $outputDir -Force - $tmp | Remove-Item - - - name: Select features - run: | - switch ("${{ matrix.features }}") { - "all" { - echo "FEATURES=--all-features" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append - } - "none" { - echo "FEATURES=--no-default-features" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append - } - "default" { - echo "FEATURES=" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append - } - default { - Exit 1 - } - } - - - name: Install sccache - uses: mozilla-actions/sccache-action@v0.0.9 - - - uses: msys2/setup-msys2@v2 - - - name: build tests - run: | - cargo nextest run --workspace ${{ env.FEATURES }} --lib --bins --tests --target ${{ matrix.target }} --no-run - - - name: list ignored tests - run: | - cargo nextest list --workspace ${{ env.FEATURES }} --lib --bins --tests --target ${{ matrix.target }} --run-ignored ignored-only - - - name: tests - run: | - mkdir -p output - cargo nextest run --workspace ${{ env.FEATURES }} --lib --bins --tests --profile ci --target ${{ matrix.target }} --run-ignored ${{ inputs.flaky && 'all' || 'default' }} --no-fail-fast --message-format ${{ inputs.flaky && 'libtest-json' || 'human' }} > output/${{ matrix.name }}_${{ matrix.features }}_${{ matrix.rust }}.json - env: - RUST_LOG: ${{ runner.debug && 'TRACE' || 'DEBUG'}} - NEXTEST_EXPERIMENTAL_LIBTEST_JSON: 1 - - - name: upload results - if: ${{ failure() && inputs.flaky }} - uses: actions/upload-artifact@v6 - with: - name: libtest_run_${{ github.run_number }}-${{ github.run_attempt }}-${{ matrix.name }}_${{ matrix.features }}_${{ matrix.rust }}.json - path: output - retention-days: 1 - compression-level: 0 + - name: Checkout + uses: actions/checkout@v6 + with: + ref: ${{ inputs.git-ref }} + + - name: Install ${{ matrix.rust }} + run: | + rustup toolchain install ${{ matrix.rust }} + rustup toolchain default ${{ matrix.rust }} + rustup target add ${{ matrix.target }} + rustup set default-host ${{ matrix.target }} + + - name: Install cargo-nextest + shell: powershell + run: | + $tmp = New-TemporaryFile | Rename-Item -NewName { $_ -replace 'tmp$', 'zip' } -PassThru + Invoke-WebRequest -OutFile $tmp https://get.nexte.st/latest/windows + $outputDir = if ($Env:CARGO_HOME) { Join-Path $Env:CARGO_HOME "bin" } else { "~/.cargo/bin" } + $tmp | Expand-Archive -DestinationPath $outputDir -Force + $tmp | Remove-Item + + - name: Select features + run: | + switch ("${{ matrix.features }}") { + "all" { + echo "FEATURES=--all-features" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append + } + "none" { + echo "FEATURES=--no-default-features" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append + } + "default" { + echo "FEATURES=" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append + } + default { + Exit 1 + } + } + + - name: Install sccache + uses: mozilla-actions/sccache-action@v0.0.9 + + - uses: msys2/setup-msys2@v2 + + - name: build tests + run: | + cargo nextest run --workspace ${{ env.FEATURES }} --lib --bins --tests --target ${{ matrix.target }} --no-run + + - name: list ignored tests + run: | + cargo nextest list --workspace ${{ env.FEATURES }} --lib --bins --tests --target ${{ matrix.target }} --run-ignored ignored-only + + - name: tests + run: | + mkdir -p output + cargo nextest run --workspace ${{ env.FEATURES }} --lib --bins --tests --profile ci --target ${{ matrix.target }} --run-ignored ${{ inputs.flaky && 'all' || 'default' }} --no-fail-fast --message-format ${{ inputs.flaky && 'libtest-json' || 'human' }} > output/${{ matrix.name }}_${{ matrix.features }}_${{ matrix.rust }}.json + env: + RUST_LOG: ${{ runner.debug && 'TRACE' || 'DEBUG'}} + NEXTEST_EXPERIMENTAL_LIBTEST_JSON: 1 + + - name: upload results + if: ${{ failure() && inputs.flaky }} + uses: actions/upload-artifact@v6 + with: + name: libtest_run_${{ github.run_number }}-${{ github.run_attempt }}-${{ matrix.name }}_${{ matrix.features }}_${{ matrix.rust }}.json + path: output + retention-days: 1 + compression-level: 0 diff --git a/.github/workflows/wasm.yaml b/.github/workflows/wasm.yaml index 027a2a11..b480bfcd 100644 --- a/.github/workflows/wasm.yaml +++ b/.github/workflows/wasm.yaml @@ -45,4 +45,4 @@ jobs: # some non-Wasm-compatible code made it into the final code. - name: Ensure no 'import "env"' in Wasm run: | - ! wasm-tools print --skeleton target/wasm32-unknown-unknown/debug/iroh_n0des.wasm | grep 'import "env"' + ! wasm-tools print --skeleton target/wasm32-unknown-unknown/debug/iroh_services.wasm | grep 'import "env"' diff --git a/Cargo.lock b/Cargo.lock index bddee898..af2b7561 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1572,43 +1572,6 @@ dependencies = [ "syn", ] -[[package]] -name = "iroh-n0des" -version = "0.10.0" -dependencies = [ - "anyhow", - "built", - "bytes", - "derive_more", - "ed25519-dalek", - "futures-buffered", - "getrandom 0.3.4", - "iroh", - "iroh-metrics", - "iroh-quinn", - "iroh-tickets", - "irpc", - "irpc-iroh", - "n0-error", - "n0-future", - "portmapper", - "postcard", - "rand", - "rcan", - "serde", - "serde_json", - "ssh-key", - "strum", - "temp_env_vars", - "thiserror", - "time", - "tokio", - "tokio-util", - "tracing", - "tracing-subscriber", - "uuid", -] - [[package]] name = "iroh-quinn" version = "0.16.1" @@ -1716,6 +1679,43 @@ dependencies = [ "z32", ] +[[package]] +name = "iroh-services" +version = "0.10.0" +dependencies = [ + "anyhow", + "built", + "bytes", + "derive_more", + "ed25519-dalek", + "futures-buffered", + "getrandom 0.3.4", + "iroh", + "iroh-metrics", + "iroh-quinn", + "iroh-tickets", + "irpc", + "irpc-iroh", + "n0-error", + "n0-future", + "portmapper", + "postcard", + "rand", + "rcan", + "serde", + "serde_json", + "ssh-key", + "strum", + "temp_env_vars", + "thiserror", + "time", + "tokio", + "tokio-util", + "tracing", + "tracing-subscriber", + "uuid", +] + [[package]] name = "iroh-tickets" version = "0.3.0" diff --git a/Cargo.toml b/Cargo.toml index 55833382..a56ac99a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,12 @@ [package] -name = "iroh-n0des" +name = "iroh-services" version = "0.10.0" edition = "2024" readme = "README.md" description = "p2p quic connections dialed by public key" license = "MIT OR Apache-2.0" authors = ["n0 team"] -repository = "https://github.com/n0-computer/iroh-n0des" +repository = "https://github.com/n0-computer/iroh-services" keywords = ["quic", "networking", "holepunching", "p2p"] rust-version = "1.89" diff --git a/README.md b/README.md index 37103100..1a1a5a03 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,31 @@ -# iroh-n0des +# iroh-services + +Client library for interacting with [iroh](https://services.iroh.computer). Clients attach to the endpoint in your app to add features like metrics aggregation, network diagnostics, etc. + +```rust +use iroh::Endpoint; +use iroh_services::Client; + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + let endpoint = Endpoint::bind().await?; + + // needs IROH_SERVICES_API_KEY set to an environment variable + // as long as client variable is not dropped it wil + // push endpoint metrics to iroh services in the background, by default + // every 60 seconds + let client = Client::builder(&endpoint) + .api_key_from_env()? + .build() + .await?; + + // we can also ping the service just to confirm everything is working + client.ping().await?; + + Ok(()) +} +``` -An iroh protocol to interact with n0des, using iroh itself. ## License diff --git a/examples/net_diagnostics.rs b/examples/net_diagnostics.rs index 9144ac70..0a120f8a 100644 --- a/examples/net_diagnostics.rs +++ b/examples/net_diagnostics.rs @@ -1,39 +1,38 @@ //! Network diagnostics example with a ClientHost. //! -//! Demonstrates how to set up a ClientHost that accepts incoming n0des RPC +//! Demonstrates how to set up a ClientHost that accepts incoming services RPC //! requests, and run a full network diagnostics report from an existing iroh //! Endpoint — covering NAT type, UDP connectivity, relay latency, and port //! mapping protocol availability. //! //! The ClientHost registers on the [CLIENT_HOST_ALPN], so that the remote -//! n0des service can dial back into this endpoint to request diagnostics. +//! services service can dial back into this endpoint to request diagnostics. //! //! Run with: cargo run --features=net_diagnostics,client_host --example net_diagnostics use anyhow::Result; use iroh::{Endpoint, protocol::Router}; -use iroh_n0des::{ - API_SECRET_ENV_VAR_NAME, ApiSecret, CLIENT_HOST_ALPN, Client, ClientHost, - caps::NetDiagnosticsCap, +use iroh_services::{ + API_KEY_ENV_VAR_NAME, ApiKey, CLIENT_HOST_ALPN, Client, ClientHost, caps::NetDiagnosticsCap, }; #[tokio::main] async fn main() -> Result<()> { - // 1. Create an endpoint that will both dial n0des and accept incoming - // requests from the n0des service via a ClientHost. + // 1. Create an endpoint that will both dial services and accept incoming + // requests from the services service via a ClientHost. let endpoint = Endpoint::builder().bind().await?; // 2. Parse the ApiSecret separately so we can extract the remote // EndpointID. Normally we'd pass it straight to the client builder. - let secret = ApiSecret::from_env_var(API_SECRET_ENV_VAR_NAME)?; + let secret = ApiKey::from_env_var(API_KEY_ENV_VAR_NAME)?; - // 3. Build a Client that dials n0des (as in all other examples). + // 3. Build a Client that dials services (as in all other examples). let client = Client::builder(&endpoint) - .api_secret(secret.clone())? + .api_key(secret.clone())? .build() .await?; // 4. grant the ability to get diagnostics to the remote EndpointID associated - // with our project on n0des. This will create a capability token, send it to + // with our project on services. This will create a capability token, send it to // the remote for storage & confirm receipt. We do this in a task to avoid // blocking the local node startup in the rare case that remote endpoint is // down when this process starts. @@ -46,14 +45,14 @@ async fn main() -> Result<()> { .unwrap(); }); - // 5. Set up a ClientHost so n0des can dial *back* into this endpoint. + // 5. Set up a ClientHost so services can dial *back* into this endpoint. // Incoming connections must present an RCAN issued by this endpoint. let host = ClientHost::new(&endpoint); let router = Router::builder(endpoint) .accept(CLIENT_HOST_ALPN, host) .spawn(); - // 6. Run diagnostics locally (pass true to also upload results to n0des). + // 6. Run diagnostics locally (pass true to also upload results to services). println!("Running network diagnostics...\n"); let report = client.net_diagnostics(false).await?; println!("{:?}", report); diff --git a/examples/quickstart.rs b/examples/quickstart.rs index 39b7a766..6f97ac92 100644 --- a/examples/quickstart.rs +++ b/examples/quickstart.rs @@ -1,14 +1,14 @@ use iroh::Endpoint; -use iroh_n0des::Client; +use iroh_services::Client; #[tokio::main] async fn main() -> anyhow::Result<()> { let endpoint = Endpoint::bind().await?; - // needs N0DES_API_SECRET set to an environment variable - // client will now push endpoint metrics to n0des + // needs IROH_SERVICES_API_KEY set to an environment variable + // client will now push endpoint metrics to services let client = Client::builder(&endpoint) - .api_secret_from_env()? + .api_key_from_env()? .build() .await?; diff --git a/src/api_secret.rs b/src/api_key.rs similarity index 84% rename from src/api_secret.rs rename to src/api_key.rs index e5904e35..080f6c7e 100644 --- a/src/api_secret.rs +++ b/src/api_key.rs @@ -10,17 +10,17 @@ use iroh::{EndpointAddr, EndpointId, SecretKey, TransportAddr}; use iroh_tickets::{ParseError, Ticket}; use serde::{Deserialize, Serialize}; -/// The secret material used to connect your n0des.iroh.computer project. The +/// The secret material used to connect your services.iroh.computer project. The /// value of these should be treated like any other API key: guard them carefully. #[derive(Debug, Clone)] -pub struct ApiSecret { +pub struct ApiKey { /// ED25519 secret used to construct rcans from pub secret: SecretKey, - /// the n0des endpoint to direct requests to + /// the services endpoint to direct requests to pub remote: EndpointAddr, } -impl Display for ApiSecret { +impl Display for ApiKey { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", Ticket::serialize(self)) } @@ -35,22 +35,22 @@ struct Variant0EndpointAddr { /// Wire format for [`Ticket`]. #[derive(Serialize, Deserialize)] enum TicketWireFormat { - Variant0(Variant0N0desTicket), + Variant0(Variant0servicesTicket), } #[derive(Serialize, Deserialize)] -struct Variant0N0desTicket { +struct Variant0servicesTicket { secret: SecretKey, addr: Variant0EndpointAddr, } -impl Ticket for ApiSecret { +impl Ticket for ApiKey { // KIND is the constant that's added to the front of a serialized ticket // string. It should be a short, human readable string - const KIND: &'static str = "n0des"; + const KIND: &'static str = "services"; fn to_bytes(&self) -> Vec { - let data = TicketWireFormat::Variant0(Variant0N0desTicket { + let data = TicketWireFormat::Variant0(Variant0servicesTicket { secret: self.secret.clone(), addr: Variant0EndpointAddr { endpoint_id: self.remote.id, @@ -62,7 +62,7 @@ impl Ticket for ApiSecret { fn from_bytes(bytes: &[u8]) -> Result { let res: TicketWireFormat = postcard::from_bytes(bytes)?; - let TicketWireFormat::Variant0(Variant0N0desTicket { secret, addr }) = res; + let TicketWireFormat::Variant0(Variant0servicesTicket { secret, addr }) = res; Ok(Self { secret, remote: EndpointAddr { @@ -73,7 +73,7 @@ impl Ticket for ApiSecret { } } -impl FromStr for ApiSecret { +impl FromStr for ApiKey { type Err = ParseError; fn from_str(s: &str) -> Result { @@ -81,7 +81,7 @@ impl FromStr for ApiSecret { } } -impl ApiSecret { +impl ApiKey { /// Creates a new ticket. pub fn new(secret: SecretKey, remote: impl Into) -> Self { Self { diff --git a/src/caps.rs b/src/caps.rs index ba176f2e..6ddbb0cc 100644 --- a/src/caps.rs +++ b/src/caps.rs @@ -126,7 +126,7 @@ impl Caps { Self::V0(CapSet::new(caps)) } - /// the class of capabilities that n0des will accept when deriving from a + /// the class of capabilities that services will accept when deriving from a /// shared secret like an [ApiSecret]. These should be "client" capabilities: /// typically for users of an app /// @@ -135,8 +135,8 @@ impl Caps { Self::new([Cap::Client]) } - /// The maximum set of capabilities. n0des will only accept these capabilities - /// when deriving from a secret that is registered with n0des, like an SSH key + /// The maximum set of capabilities. services will only accept these capabilities + /// when deriving from a secret that is registered with services, like an SSH key pub fn all() -> Self { Self::new([Cap::All]) } diff --git a/src/client.rs b/src/client.rs index f4265d71..7872bc5c 100644 --- a/src/client.rs +++ b/src/client.rs @@ -19,25 +19,25 @@ use crate::net_diagnostics::{DiagnosticsReport, checks::run_diagnostics}; #[cfg(feature = "net_diagnostics")] use crate::protocol::PutNetworkDiagnostics; use crate::{ - api_secret::ApiSecret, + api_key::ApiKey, caps::Caps, - protocol::{ALPN, Auth, N0desClient, Ping, Pong, PutMetrics, RemoteError}, + protocol::{ALPN, Auth, Ping, Pong, PutMetrics, RemoteError, ServicesClient}, }; -/// Client is the main handle for interacting with n0des. It communicates with -/// n0des entirely through an iroh endpoint, and is configured through a builder. +/// Client is the main handle for interacting with services. It communicates with +/// services entirely through an iroh endpoint, and is configured through a builder. /// Client requires either an Ssh Key or [`ApiSecret`] /// /// ```no_run -/// use iroh_n0des::Client; +/// use iroh_services::Client; /// /// async fn build_client() -> anyhow::Result<()> { /// let endpoint = iroh::Endpoint::bind().await?; /// -/// // needs N0DES_API_SECRET set to an environment variable -/// // client will now push endpoint metrics to n0des. +/// // needs IROH_SERVICES_API_KEY set to an environment variable +/// // client will now push endpoint metrics to services. /// let client = Client::builder(&endpoint) -/// .api_secret_from_str("MY_API_SECRET")? +/// .api_key_from_str("MY_API_key")? /// .build() /// .await; /// @@ -45,7 +45,7 @@ use crate::{ /// } /// ``` /// -/// [`ApiSecret`]: crate::api_secret::ApiSecret +/// [`ApiSecret`]: crate::api_key::ApiSecret #[derive(Debug, Clone)] pub struct Client { // owned clone of the endpoint for diagnostics, and for connection restarts on actor close @@ -55,7 +55,7 @@ pub struct Client { _actor_task: Arc>, } -/// ClientBuilder provides configures and builds a n0des client, typically +/// ClientBuilder provides configures and builds a services client, typically /// created with [`Client::builder`] pub struct ClientBuilder { #[allow(dead_code)] @@ -68,7 +68,7 @@ pub struct ClientBuilder { } const DEFAULT_CAP_EXPIRY: Duration = Duration::from_secs(60 * 60 * 24 * 30); // 1 month -pub const API_SECRET_ENV_VAR_NAME: &str = "N0DES_API_SECRET"; +pub const API_KEY_ENV_VAR_NAME: &str = "IROH_SERVICES_API_KEY"; impl ClientBuilder { pub fn new(endpoint: &Endpoint) -> Self { @@ -85,7 +85,7 @@ impl ClientBuilder { } } - /// Register a metrics group to forward to n0des + /// Register a metrics group to forward to services /// /// The default registered metrics uses only the endpoint pub fn register_metrics_group(mut self, metrics_group: Arc) -> Self { @@ -107,25 +107,25 @@ impl ClientBuilder { self } - /// Check N0DES_API_SECRET environment variable for a valid API secret - pub fn api_secret_from_env(self) -> Result { - let ticket = ApiSecret::from_env_var(API_SECRET_ENV_VAR_NAME)?; - self.api_secret(ticket) + /// Check IROH_SERVICES_API_KEY environment variable for a valid API secret + pub fn api_key_from_env(self) -> Result { + let ticket = ApiKey::from_env_var(API_KEY_ENV_VAR_NAME)?; + self.api_key(ticket) } /// set client API secret from an encoded string - pub fn api_secret_from_str(self, secret_key: &str) -> Result { - let key = ApiSecret::from_str(secret_key).context("invalid n0des api secret")?; - self.api_secret(key) + pub fn api_key_from_str(self, secret_key: &str) -> Result { + let key = ApiKey::from_str(secret_key).context("invalid services api secret")?; + self.api_key(key) } - /// Use a shared secret & remote n0des endpoint ID contained within a ticket - /// to construct a n0des client. The resulting client will have "Client" + /// Use a shared secret & remote services endpoint ID contained within a ticket + /// to construct a services client. The resulting client will have "Client" /// capabilities. /// /// API secrets include remote details within them, and will set both the /// remote and rcan values on the builder - pub fn api_secret(mut self, ticket: ApiSecret) -> Result { + pub fn api_key(mut self, ticket: ApiKey) -> Result { let local_id = self.endpoint.id(); let rcan = crate::caps::create_api_token_from_secret_key( ticket.secret, @@ -173,7 +173,7 @@ impl ClientBuilder { } /// Sets the remote to dial, must be provided either directly by calling - /// this method, or through calling the api_secret builder methods. + /// this method, or through calling the api_key builder methods. pub fn remote(mut self, remote: impl Into) -> Self { self.remote = Some(remote.into()); self @@ -182,12 +182,12 @@ impl ClientBuilder { /// Create a new client, connected to the provide service node #[must_use = "dropping the client will silently cancel all client tasks"] pub async fn build(self) -> Result { - debug!("starting iroh-n0des client"); + debug!("starting iroh-services client"); let remote = self.remote.ok_or(BuildError::MissingRemote)?; let capabilities = self.cap.ok_or(BuildError::MissingCapability)?; let conn = IrohLazyRemoteConnection::new(self.endpoint.clone(), remote, ALPN.to_vec()); - let client = N0desClient::boxed(conn); + let client = ServicesClient::boxed(conn); let (tx, rx) = tokio::sync::mpsc::channel(1); let metrics_task = AbortOnDropHandle::new(n0_future::task::spawn( @@ -268,7 +268,7 @@ impl Client { .map_err(Error::Remote) } - /// immediately send a single dump of metrics to n0des. It's not necessary + /// immediately send a single dump of metrics to services. It's not necessary /// to call this function if you're using a non-zero metrics interval, /// which will automatically propagate metrics on the set interval for you pub async fn push_metrics(&self) -> Result<(), Error> { @@ -284,7 +284,7 @@ impl Client { } /// Grant capabilities to a remote endpoint. Creates a signed RCAN token - /// and sends it to n0des for storage. The remote can then use this token + /// and sends it to services for storage. The remote can then use this token /// when dialing back to authorize its requests. #[cfg(feature = "client_host")] pub async fn grant_capability( @@ -359,7 +359,7 @@ enum ClientActorMessage { struct ClientActor { capabilities: Rcan, - client: N0desClient, + client: ServicesClient, session_id: Uuid, authorized: bool, } @@ -514,9 +514,9 @@ mod tests { use crate::{ Client, - api_secret::ApiSecret, + api_key::ApiKey, caps::{Cap, Caps}, - client::API_SECRET_ENV_VAR_NAME, + client::API_KEY_ENV_VAR_NAME, }; #[tokio::test] @@ -526,9 +526,9 @@ mod tests { let mut rng = rand::rng(); let shared_secret = SecretKey::generate(&mut rng); let fake_endpoint_id = SecretKey::generate(&mut rng).public(); - let api_secret = ApiSecret::new(shared_secret.clone(), fake_endpoint_id); + let api_key = ApiKey::new(shared_secret.clone(), fake_endpoint_id); unsafe { - std::env::set_var(API_SECRET_ENV_VAR_NAME, api_secret.to_string()); + std::env::set_var(API_KEY_ENV_VAR_NAME, api_key.to_string()); }; let endpoint = Endpoint::empty_builder(iroh::RelayMode::Disabled) @@ -536,7 +536,7 @@ mod tests { .await .unwrap(); - let builder = Client::builder(&endpoint).api_secret_from_env().unwrap(); + let builder = Client::builder(&endpoint).api_key_from_env().unwrap(); let fake_endpoint_addr: EndpointAddr = fake_endpoint_id.into(); assert_eq!(builder.remote, Some(fake_endpoint_addr)); @@ -556,7 +556,7 @@ mod tests { let mut rng = rand::rng(); let shared_secret = SecretKey::generate(&mut rng); let fake_endpoint_id = SecretKey::generate(&mut rng).public(); - let api_secret = ApiSecret::new(shared_secret.clone(), fake_endpoint_id); + let api_key = ApiKey::new(shared_secret.clone(), fake_endpoint_id); let endpoint = Endpoint::empty_builder(iroh::RelayMode::Disabled) .bind() @@ -565,7 +565,7 @@ mod tests { let client = Client::builder(&endpoint) .disable_metrics_interval() - .api_secret(api_secret) + .api_key(api_key) .unwrap() .build() .await diff --git a/src/client_host.rs b/src/client_host.rs index 7f595d4b..045d72c2 100644 --- a/src/client_host.rs +++ b/src/client_host.rs @@ -16,7 +16,7 @@ use crate::{ }; /// The ALPN for sending messages from the cloud node to the client. -pub const CLIENT_HOST_ALPN: &[u8] = b"n0/n0des-client-host/1"; +pub const CLIENT_HOST_ALPN: &[u8] = b"n0/services-client-host/1"; pub type ClientHostClient = irpc::Client; @@ -153,7 +153,7 @@ mod tests { use crate::{ ALPN, caps::create_grant_token, - protocol::{Auth, N0desClient, RunNetworkDiagnostics}, + protocol::{Auth, RunNetworkDiagnostics, servicesClient}, }; #[tokio::test] @@ -236,7 +236,7 @@ mod tests { let conn = IrohLazyRemoteConnection::new(client_ep.clone(), server_ep.addr(), ALPN.to_vec()); - let client = N0desClient::boxed(conn); + let client = servicesClient::boxed(conn); // auth should fail because the RCAN issuer is the client, not the server let result = client.rpc(Auth { caps: rcan }).await; diff --git a/src/lib.rs b/src/lib.rs index ab837ec8..20feac80 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,20 +1,20 @@ -//! iroh-n0des is the client side of interacting with [n0des]. n0des gives +//! iroh-services is the client side of interacting with [services]. services gives //! visibility into a running iroh network by pushing metrics aggregations //! from [iroh] endpoints into a central hub for monitoring. //! //! Typical setup looks something like this: //! ```no_run //! use iroh::Endpoint; -//! use iroh_n0des::Client; +//! use iroh_services::Client; //! //! #[tokio::main] //! async fn main() -> anyhow::Result<()> { //! let endpoint = Endpoint::bind().await?; //! -//! // needs N0DES_API_SECRET set to an environment variable -//! // client will now push endpoint metrics to n0des. +//! // needs IROH_SERVICES_API_KEY set to an environment variable +//! // client will now push endpoint metrics to services. //! let client = Client::builder(&endpoint) -//! .api_secret_from_env()? +//! .api_key_from_env()? //! .build() //! .await?; //! @@ -25,14 +25,14 @@ //! } //! ``` //! -//! [n0des]: https://n0des.iroh.computer +//! [services]: https://services.iroh.computer //! [iroh]: https://iroh.computer mod client; #[cfg(feature = "client_host")] mod client_host; -pub mod api_secret; +pub mod api_key; pub mod caps; pub mod net_diagnostics; pub mod protocol; @@ -42,7 +42,7 @@ mod built_info { } /// Version of this crate. -pub const IROH_N0DES_VERSION: &str = built_info::PKG_VERSION; +pub const IROH_SERVICES_VERSION: &str = built_info::PKG_VERSION; /// Version of iroh this crate was built against. pub static IROH_VERSION: std::sync::LazyLock<&str> = std::sync::LazyLock::new(|| { @@ -61,7 +61,7 @@ pub use iroh_metrics::Registry; #[cfg(feature = "net_diagnostics")] pub use self::net_diagnostics::{DiagnosticsReport, checks::run_diagnostics}; pub use self::{ - api_secret::ApiSecret, - client::{API_SECRET_ENV_VAR_NAME, Client, ClientBuilder}, + api_key::ApiKey, + client::{API_KEY_ENV_VAR_NAME, Client, ClientBuilder}, protocol::ALPN, }; diff --git a/src/net_diagnostics.rs b/src/net_diagnostics.rs index 27ff56bd..a2fa8b28 100644 --- a/src/net_diagnostics.rs +++ b/src/net_diagnostics.rs @@ -21,7 +21,7 @@ pub struct DiagnosticsReport { #[serde(default)] pub iroh_version: String, #[serde(default)] - pub iroh_n0des_version: String, + pub iroh_services_version: String, } /// Port mapping protocol availability on the LAN. @@ -95,7 +95,7 @@ pub mod checks { direct_addrs, portmap_probe, iroh_version: crate::IROH_VERSION.to_string(), - iroh_n0des_version: crate::IROH_N0DES_VERSION.to_string(), + iroh_services_version: crate::IROH_SERVICES_VERSION.to_string(), }) } diff --git a/src/protocol.rs b/src/protocol.rs index ca9514d6..e8f66639 100644 --- a/src/protocol.rs +++ b/src/protocol.rs @@ -9,12 +9,12 @@ use crate::{caps::Caps, net_diagnostics::DiagnosticsReport}; /// The main ALPN for connecting from the client to the cloud node. pub const ALPN: &[u8] = b"/iroh/n0des/1"; -pub type N0desClient = irpc::Client; +pub type ServicesClient = irpc::Client; -#[rpc_requests(message = N0desMessage)] +#[rpc_requests(message = IrohServicesMessage)] #[derive(Debug, Serialize, Deserialize)] #[allow(clippy::large_enum_variant)] -pub enum N0desProtocol { +pub enum IrohServicesProtocol { #[rpc(tx=oneshot::Sender<()>)] Auth(Auth), #[rpc(tx=oneshot::Sender>)]