From 3fbc1a56ef3a7d56e9e4200f29bc116331d225d0 Mon Sep 17 00:00:00 2001 From: devkelley <105753233+devkelley@users.noreply.github.com> Date: Thu, 7 Dec 2023 14:07:30 -0800 Subject: [PATCH] Update Ibeji Dockerfiles (#81) * Remove Containerize feature and add aarch64 targets * Updated Dockerfiles for amd64 and arm64 * Update README's to reflect container changes * Fix link and linting * make optional args more concise * remove unused comment --- .cargo/config.toml | 3 + .github/workflows/check-spelling.yml | 1 - Dockerfile => Dockerfile.amd64 | 53 +++- Dockerfile.integrated => Dockerfile.arm64 | 63 +++-- README.md | 5 +- container/.accepted_words.txt | 5 + container/README.md | 228 +++++++++++++++--- container/config/docker.env | 9 - container/config/podman.env | 9 - container/scripts/argument_sanitizer.sh | 61 +++++ container/scripts/container_startup.sh | 16 ++ core/common/Cargo.toml | 3 - core/common/src/utils.rs | 41 +--- core/invehicle-digital-twin/Cargo.toml | 3 +- core/invehicle-digital-twin/src/main.rs | 8 +- core/module/managed_subscribe/Cargo.toml | 3 - .../src/managed_subscribe_interceptor.rs | 4 +- ...file.consumer => Dockerfile.samples.amd64} | 46 ++-- ...file.provider => Dockerfile.samples.arm64} | 56 +++-- samples/common/.cargo/config.toml | 3 + samples/common/Cargo.toml | 5 +- samples/common/src/utils.rs | 46 +--- samples/container/.accepted_words.txt | 93 ------- samples/container/README.md | 157 ------------ samples/container/config/docker.env | 9 - samples/container/config/podman.env | 9 - samples/managed_subscribe/Cargo.toml | 5 +- .../managed_subscribe/consumer/src/main.rs | 4 +- .../provider/src/provider_impl.rs | 5 +- samples/property/Cargo.toml | 5 +- samples/property/provider/src/main.rs | 8 +- samples/streaming/.cargo/config.toml | 3 + samples/streaming/Cargo.toml | 4 + 33 files changed, 475 insertions(+), 498 deletions(-) create mode 100644 .cargo/config.toml rename Dockerfile => Dockerfile.amd64 (64%) rename Dockerfile.integrated => Dockerfile.arm64 (55%) delete mode 100644 container/config/docker.env delete mode 100644 container/config/podman.env create mode 100755 container/scripts/argument_sanitizer.sh create mode 100755 container/scripts/container_startup.sh rename samples/{Dockerfile.consumer => Dockerfile.samples.amd64} (75%) rename samples/{Dockerfile.provider => Dockerfile.samples.arm64} (64%) create mode 100644 samples/common/.cargo/config.toml delete mode 100644 samples/container/.accepted_words.txt delete mode 100644 samples/container/README.md delete mode 100644 samples/container/config/docker.env delete mode 100644 samples/container/config/podman.env create mode 100644 samples/streaming/.cargo/config.toml diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 00000000..c3b54de3 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,3 @@ +[target.aarch64-unknown-linux-gnu] +linker = "aarch64-linux-gnu-gcc" +rustflags = [ "-C", "target-feature=+crt-static", "-C", "link-arg=-lgcc" ] diff --git a/.github/workflows/check-spelling.yml b/.github/workflows/check-spelling.yml index 086c23a8..61768720 100644 --- a/.github/workflows/check-spelling.yml +++ b/.github/workflows/check-spelling.yml @@ -21,6 +21,5 @@ jobs: ./tools/check_spelling.sh ./core/common/README.md ./tools/check_spelling.sh ./dtdl-parser/README.md ./tools/check_spelling.sh ./docs/design/README.md - ./tools/check_spelling.sh ./samples/container/README.md ./tools/check_spelling.sh ./samples/managed_subscribe/README.md shell: bash diff --git a/Dockerfile b/Dockerfile.amd64 similarity index 64% rename from Dockerfile rename to Dockerfile.amd64 index 41e3848c..d5740afc 100644 --- a/Dockerfile +++ b/Dockerfile.amd64 @@ -10,24 +10,37 @@ # Create a stage for building the application. ARG RUST_VERSION=1.72.1 -FROM docker.io/library/rust:${RUST_VERSION}-slim-bullseye AS build ARG APP_NAME=invehicle-digital-twin +ARG FEATURES="" +ARG UID=10001 + +FROM docker.io/library/rust:${RUST_VERSION}-slim-bullseye AS build +ARG APP_NAME +ARG FEATURES WORKDIR /sdv COPY ./ . +# Check that APP_NAME argument is valid. +RUN /sdv/container/scripts/argument_sanitizer.sh \ + --arg-value "${APP_NAME}" \ + --regex "^[a-zA-Z_0-9-]+$" || \ + ( echo "Argument sanitizer failed for ARG 'APP_NAME'"; exit 1 ) + +# Check that FEATURES argument is valid if the argument is not empty. +# The regex checks if there is one or more features separated by a single space. +RUN if [ -n "${FEATURES}" ]; then \ + /sdv/container/scripts/argument_sanitizer.sh \ + --arg-value "${FEATURES}" \ + --regex "^[a-zA-Z_0-9-]+(?: [a-zA-Z_0-9-]+)*$" || \ + ( echo "Argument sanitizer failed for ARG 'FEATURES'"; exit 1 ) \ + fi + # Add Build dependencies. RUN apt update && apt upgrade -y && apt install -y protobuf-compiler -# Check that APP_NAME argument is valid. -RUN sanitized=$(echo "${APP_NAME}" | tr -dc '^[a-zA-Z_0-9-]+$'); \ -[ "$sanitized" = "${APP_NAME}" ] || { \ - echo "ARG 'APP_NAME' is invalid. APP_NAME='${APP_NAME}' sanitized='${sanitized}'"; \ - exit 1; \ -} - -# Build the application with the 'containerize' feature. -RUN cargo build --release -p "${APP_NAME}" --features "containerize" +# Build the application (with features if provided). +RUN cargo build --release -p "${APP_NAME}" --features "${FEATURES}" # Copy the built application to working directory. RUN cp ./target/release/"${APP_NAME}" /sdv/service @@ -44,6 +57,16 @@ RUN cp ./target/release/"${APP_NAME}" /sdv/service # reproducability is important, consider using a digest # (e.g., debian@sha256:ac707220fbd7b67fc19b112cee8170b41a9e97f703f588b2cdbbcdcecdd8af57). FROM docker.io/library/debian:bullseye-slim AS final +ARG UID + +# Copy container scripts. +COPY ./container/scripts/*.sh /sdv/scripts/ + +# Check that UID argument is valid. +RUN /sdv/scripts/argument_sanitizer.sh \ + --arg-value "${UID}" \ + --regex "^[0-9]+$" || \ + ( echo "Argument sanitizer failed for ARG 'UID'"; exit 1 ) # Create a non-privileged user that the app will run under. # See https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#user @@ -56,6 +79,14 @@ RUN adduser \ --no-create-home \ --uid "${UID}" \ appuser + +# Create and add user ownership to config directory. +RUN mkdir -p /sdv/config +RUN chown appuser /sdv/config + +# Create mnt directory to copy override configs into. +RUN mkdir -p /mnt/config + USER appuser WORKDIR /sdv @@ -73,4 +104,4 @@ COPY --from=build /sdv/container/config/standalone/ /sdv/config EXPOSE 5010 # What the container should run when it is started. -CMD ["/sdv/service"] +CMD ["/sdv/scripts/container_startup.sh"] diff --git a/Dockerfile.integrated b/Dockerfile.arm64 similarity index 55% rename from Dockerfile.integrated rename to Dockerfile.arm64 index 05c335f3..244b4e97 100644 --- a/Dockerfile.integrated +++ b/Dockerfile.arm64 @@ -10,27 +10,44 @@ # Create a stage for building the application. ARG RUST_VERSION=1.72.1 -FROM docker.io/library/rust:${RUST_VERSION}-slim-bullseye AS build ARG APP_NAME=invehicle-digital-twin +ARG FEATURES="" +ARG UID=10001 + +FROM docker.io/library/rust:${RUST_VERSION}-slim-bullseye AS build +ARG APP_NAME +ARG FEATURES WORKDIR /sdv COPY ./ . +# Check that APP_NAME argument is valid. +RUN /sdv/container/scripts/argument_sanitizer.sh \ + --arg-value "${APP_NAME}" \ + --regex "^[a-zA-Z_0-9-]+$" || \ + ( echo "Argument sanitizer failed for ARG 'APP_NAME'"; exit 1 ) + +# Check that FEATURES argument is valid if the argument is not empty. +# The regex checks if there is one or more features separated by a single space. +RUN if [ -n "${FEATURES}" ]; then \ + /sdv/container/scripts/argument_sanitizer.sh \ + --arg-value "${FEATURES}" \ + --regex "^[a-zA-Z_0-9-]+(?: [a-zA-Z_0-9-]+)*$" || \ + ( echo "Argument sanitizer failed for ARG 'FEATURES'"; exit 1 ) \ + fi + # Add Build dependencies. -RUN apt update && apt upgrade -y && apt install -y protobuf-compiler +RUN apt update && apt upgrade -y && apt install -y \ + protobuf-compiler \ + gcc-aarch64-linux-gnu -# Check that APP_NAME argument is valid. -RUN sanitized=$(echo "${APP_NAME}" | tr -dc '^[a-zA-Z_0-9-]+$'); \ -[ "$sanitized" = "${APP_NAME}" ] || { \ - echo "ARG 'APP_NAME' is invalid. APP_NAME='${APP_NAME}' sanitized='${sanitized}'"; \ - exit 1; \ -} +RUN rustup target add aarch64-unknown-linux-gnu -# Build the application with the 'containerize' feature. -RUN cargo build --release -p "${APP_NAME}" --features "containerize managed_subscribe" +# Build the application (with features if provided). +RUN cargo build --release --target=aarch64-unknown-linux-gnu -p "${APP_NAME}" --features "${FEATURES}" # Copy the built application to working directory. -RUN cp ./target/release/"${APP_NAME}" /sdv/service +RUN cp ./target/aarch64-unknown-linux-gnu/release/"${APP_NAME}" /sdv/service ################################################################################ # Create a new stage for running the application that contains the minimal @@ -43,7 +60,17 @@ RUN cp ./target/release/"${APP_NAME}" /sdv/service # most recent version of that tag when you build your Dockerfile. If # reproducability is important, consider using a digest # (e.g., debian@sha256:ac707220fbd7b67fc19b112cee8170b41a9e97f703f588b2cdbbcdcecdd8af57). -FROM docker.io/library/debian:bullseye-slim AS final +FROM docker.io/arm64v8/debian:bullseye-slim AS final +ARG UID + +# Copy container scripts. +COPY ./container/scripts/*.sh /sdv/scripts/ + +# Check that UID argument is valid. +RUN /sdv/scripts/argument_sanitizer.sh \ + --arg-value "${UID}" \ + --regex "^[0-9]+$" || \ + ( echo "Argument sanitizer failed for ARG 'UID'"; exit 1 ) # Create a non-privileged user that the app will run under. # See https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#user @@ -56,6 +83,14 @@ RUN adduser \ --no-create-home \ --uid "${UID}" \ appuser + +# Create and add user ownership to config directory. +RUN mkdir -p /sdv/config +RUN chown appuser /sdv/config + +# Create mnt directory to copy override configs into. +RUN mkdir -p /mnt/config + USER appuser WORKDIR /sdv @@ -67,10 +102,10 @@ ENV IBEJI_HOME=/sdv/config COPY --from=build /sdv/service /sdv/ # Copy configuration for service. -COPY --from=build /sdv/container/config/integrated/ /sdv/config +COPY --from=build /sdv/container/config/standalone/ /sdv/config # Expose the port that the application listens on. EXPOSE 5010 # What the container should run when it is started. -CMD ["/sdv/service"] +CMD ["/sdv/scripts/container_startup.sh"] diff --git a/README.md b/README.md index 75ce3775..1f8e0d5b 100644 --- a/README.md +++ b/README.md @@ -310,9 +310,8 @@ rather than having it statically provided in their respective config file, then ## Running in a Container -To run the In-Vehicle Digital Twin Service in a container, please refer to [Ibeji Containerization](./container/README.md). - -To run the samples in a container, please refer to [Samples Containerization](./samples/container/README.md). +Please refer to [Ibeji Containers](./container/README.md#ibeji-containers) for information on how +build and run the In-Vehicle Digital Twin Service or the Sample Applications in a container. ## Trademarks diff --git a/container/.accepted_words.txt b/container/.accepted_words.txt index 4e86eebb..5158ffe4 100644 --- a/container/.accepted_words.txt +++ b/container/.accepted_words.txt @@ -1,5 +1,9 @@ +aarch Agemo agemo +amd +APP +arg br build cargo @@ -54,6 +58,7 @@ loopback md microsoft minimalistic +mnt mosquitto Mosquitto mqtt diff --git a/container/README.md b/container/README.md index 06d9363e..a2fe9716 100644 --- a/container/README.md +++ b/container/README.md @@ -1,119 +1,271 @@ -# Ibeji Containerization +# Ibeji Containers -This document covers how to containerize the In-Vehicle Digital Twin Service. To run the samples as -a container please refer to [Samples Containerization](../samples/container/README.md). +This document covers how to containerize the services provided in this repository. -## Running the In-Vehicle Digital Twin Service in a Container +## Dockerfile Selection -Below are the steps for running the service in a container. Note that the configuration files used -by the containerized service are cloned from [/container/config](./config/) defined in the -project's root. +### In-Vehicle Digital Twin Service -### Dockerfile +To containerize the [In-Vehicle Digital Twin Service](../core/invehicle-digital-twin/) use one of +the following dockerfiles: -There are currently two dockerfiles provided in the root directory of the project that can be built: +- [Dockerfile.amd64](../Dockerfile.amd64) - For x86-64 architecture. +- [Dockerfile.arm64](../Dockerfile.arm64) - For aarch64 architecture. -- Dockerfile - A standalone version of the In-Vehicle Digital Twin Service -- Dockerfile.integrated - A version of the In-Vehicle Digital Twin Service that communicates with -the [Chariott Service](https://github.com/eclipse-chariott/chariott) and the -[Agemo Service](https://github.com/eclipse-chariott/Agemo). +### Sample Applications -### Docker +To containerize one of the [Ibeji Sample Applications](../samples/) use one of the following +dockerfiles: -#### Prerequisites +- [./samples/Dockerfile.samples.amd64](../samples/Dockerfile.samples.amd64) - For x86-64 +architecture. +- [./samples/Dockerfile.samples.arm64](../samples/Dockerfile.samples.arm64) - For aarch64 +architecture. + +## Configuration Defaults + +### In-Vehicle Digital Twin Service + +This repository provides default configuration files for the In-Vehicle Digital Twin Service +running in [Standalone](../container/config/standalone/) and +[Integrated](../container/config/integrated) modes. + +>Note: Integrated mode runs the In-Vehicle Digital Twin Service with the +[Chariott Service](https://github.com/eclipse-chariott/chariott) and the +[Agemo Service](https://github.com/eclipse-chariott/Agemo). Other combinations may require config +changes. + +### Sample Applications + +For the samples, this repository provides +default configuration files for the [Property Provider](../samples/container/config/provider/) and +[Property Consumer](../samples/container/config/consumer/) samples. + +>Note: Other samples may need config changes (see +[Running the Samples](../README.md#running-the-samples) for config changes). + +## Docker Containers + +### Prerequisites [Install Docker](https://docs.docker.com/engine/install/) -#### Running in Docker +### Running in Docker To run the service in a Docker container: -1. Run the following command in the project's root directory to build the docker container from the +>Note: Before running any of the following commands, replace all placeholders (wrapped with `<>`). + +1. Run the following command in the project root directory to build the docker container from the Dockerfile: ```shell - docker build -t invehicle_digital_twin -f Dockerfile . + docker build -t -f [--build-arg=APP_NAME=] [--build-arg=FEATURES=""] . + ``` + + >Note: The `FEATURES` build arg only applies to the dockerfiles for In-Vehicle Digital Twin Service. + + For example, to build an image for the `invehicle-digital-twin` project in `Standalone` mode: + + ```shell + docker build -t invehicle_digital_twin -f Dockerfile.amd64 . + ``` + + Or to build an image for the `invehicle-digital-twin` project with the `Managed Subscribe` + module: + + ```shell + docker build -t invehicle_digital_twin -f Dockerfile.amd64 --build-arg=FEATURES="managed_subscribe" . + ``` + + >Note: Modules for Ibeji are enabled via the `--features` flag. The `FEATURES` build arg passes + one or more features to the cargo build argument. If you want to add multiple features, add + each feature followed by a space e.g. `"module_1 module_2"`. + + Or to build an image for the `property-provider` sample for aarch64: + + ```shell + docker build -t property_provider -f ./samples/Dockerfile.samples.arm64 --build-arg=APP_NAME=property-provider . ``` + >Note: The build arg `APP_NAME` needs to be passed in for all sample applications to build the + correct sample. + 1. Once the container has been built, start the container in interactive mode with the following -command in the project's root directory: +command in the project root directory: + + ```shell + docker run --name --network=host -it --rm + ``` + + >Note: Most images built will require configuration overrides. See + [Running in Docker with overridden configuration](#running-in-docker-with-overridden-configuration) + for more details. + + For example, to run the `invehicle_digital_twin` standalone image built in step 1: ```shell - docker run --name invehicle_digital_twin -p 5010:5010 --env-file=./container/config/docker.env --add-host=host.docker.internal:host-gateway -it --rm invehicle_digital_twin + docker run --name invehicle_digital_twin --network=host -it --rm invehicle_digital_twin ``` + >Note: A custom network is recommended when using a container for anything but testing. + 1. To detach from the container, enter: Ctrl + p, Ctrl + q 1. To stop the container, enter: + ```shell + docker stop + ``` + + For example, to stop the `invehicle_digital_twin` container started in step 2: + ```shell docker stop invehicle_digital_twin ``` -#### Running in Docker with overridden configuration +### Running in Docker with overridden configuration Follow the steps in [Running in Docker](#running-in-docker) to build the container. 1. To run the container with overridden configuration, create your config file and set an -environment variable called IBEJI_HOME to the absolute path of the directory containing the -config file: +environment variable called CONFIG_HOME to the path to the config file: ```shell - export IBEJI_HOME={absolute path of the directory containing the config file} + export CONFIG_HOME={path to directory containing config file} ``` + For example, to set the configuration for the + [Property Provider](../samples/property/provider/) sample, run: + + ```shell + export CONFIG_HOME={path-to-repo-root}/samples/container/config/provider + ``` + + >Note: See [Configuration Defaults](#configuration-defaults) for more information. If running + a sample other than the `Property` sample you will need to create your own configuration files. + 1. Then run the container with the following command: ```shell - docker run -v ${IBEJI_HOME}:/sdv/config --name invehicle_digital_twin -p 5010:5010 --env-file=./container/config/docker.env --add-host=host.docker.internal:host-gateway -it --rm invehicle_digital_twin + docker run -v ${CONFIG_HOME}:/mnt/config --name --network=host -it --rm ``` -### Podman + For example, to run the `property_provider` image with overridden configuration: -#### Prerequisites + ```shell + docker run -v ${CONFIG_HOME}:/mnt/config --name property_provider --network=host -it --rm property_provider + ``` + +## Podman + +### Prerequisites [Install Podman](https://podman.io/docs/installation) -#### Running in Podman +### Running in Podman To run the service in a Podman container: -1. Run the following command in the project's root directory to build the podman container from the +>Note: Before running any of the following commands, replace all placeholders (wrapped with `<>`). + +1. Run the following command in the project root directory to build the podman container from the Dockerfile: ```shell - podman build -t invehicle_digital_twin:latest -f Dockerfile . + podman build -t -f [--build-arg=APP_NAME=] [--build-arg=FEATURES=""] . + ``` + + >Note: The `FEATURES` build arg only applies to the dockerfiles for In-Vehicle Digital Twin Service. + + For example, to build an image for the `invehicle-digital-twin` project in `Standalone` mode: + + ```shell + podman build -t invehicle_digital_twin -f Dockerfile.amd64 . ``` -1. Once the container has been built, start the container with the following command in the -project's root directory: + Or to build an image for the `invehicle-digital-twin` project with the `Managed Subscribe` + module: + + ```shell + podman build -t invehicle_digital_twin -f Dockerfile.amd64 --build-arg=FEATURES="managed_subscribe" . + ``` + + >Note: Modules for Ibeji are enabled via the `--features` flag. The `FEATURES` build arg passes + one or more features to the cargo build argument. If you want to add multiple features, add + each feature followed by a space e.g. `"module_1 module_2"`. + + Or to build an image for the `property-provider` sample for aarch64: + + ```shell + podman build -t property_provider -f ./samples/Dockerfile.samples.arm64 --build-arg=APP_NAME=property-provider . + ``` + + >Note: The build arg `APP_NAME` needs to be passed in for all sample applications to build the + correct sample. + +1. Once the container has been built, start the container with the following command in the project +root directory: ```shell - podman run -p 5010:5010 --env-file=./container/config/podman.env --network=slirp4netns:allow_host_loopback=true localhost/invehicle_digital_twin + podman run --network=host ``` + >Note: Most images built will require configuration overrides. See + [Running in Podman with overridden configuration](#running-in-podman-with-overridden-configuration) + for more details. + + For example, to run the `invehicle_digital_twin` image built in step 1: + + ```shell + podman run --network=host invehicle_digital_twin + ``` + + >Note: A custom network is recommended when using a container for anything but testing. + 1. To stop the container, run: + ```shell + podman ps -f ancestor= --format="{{.Names}}" | xargs podman stop + ``` + + For example, to stop the `invehicle_digital_twin` container started in step 2: + ```shell podman ps -f ancestor=localhost/invehicle_digital_twin:latest --format="{{.Names}}" | xargs podman stop ``` -#### Running in Podman with overridden configuration +### Running in Podman with overridden configuration Follow the steps in [Running in Podman](#running-in-podman) to build the container. 1. To run the container with overridden configuration, create your config file and set an -environment variable called IBEJI_HOME to the absolute path of the directory containing the -config file: +environment variable called CONFIG_HOME to the path to the config file: ```shell - export IBEJI_HOME={absolute path of the directory containing the config file} + export CONFIG_HOME={path to directory containing config file} ``` + For example, to set the configuration for the + [Property Provider](../samples/property/provider/) sample, run: + + ```shell + export CONFIG_HOME={path-to-repo-root}/samples/container/config/provider + ``` + + >Note: See [Configuration Defaults](#configuration-defaults) for more information. If running + a sample other than the `Property` sample you will need to create your own configuration files. + 1. Then run the container with the following command: ```shell - podman run --mount=type=bind,src=${IBEJI_HOME},dst=/sdv/config,ro=true -p 5010:5010 --env-file=./container/config/podman.env --network=slirp4netns:allow_host_loopback=true localhost/invehicle_digital_twin:latest + podman run --mount=type=bind,src=${CONFIG_HOME},dst=/mnt/config,ro=true --network=host + ``` + + For example, to run the `property_provider` image with overridden configuration: + + ```shell + podman run --mount=type=bind,src=${CONFIG_HOME},dst=/mnt/config,ro=true --network=host property_provider ``` diff --git a/container/config/docker.env b/container/config/docker.env deleted file mode 100644 index 56bafc6e..00000000 --- a/container/config/docker.env +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT license. -# SPDX-License-Identifier: MIT - -# DNS name used by the container to communicate with host. -HOST_GATEWAY=host.docker.internal - -# Alias for localhost to be replaced by HOST_GATEWAY if run in a container. -LOCALHOST_ALIAS=0.0.0.0 diff --git a/container/config/podman.env b/container/config/podman.env deleted file mode 100644 index 1abc4a35..00000000 --- a/container/config/podman.env +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT license. -# SPDX-License-Identifier: MIT - -# DNS name used by the container to communicate with host. -HOST_GATEWAY=host.containers.internal - -# Alias for localhost to be replaced by HOST_GATEWAY if run in a container. -LOCALHOST_ALIAS=0.0.0.0 diff --git a/container/scripts/argument_sanitizer.sh b/container/scripts/argument_sanitizer.sh new file mode 100755 index 00000000..d31613d4 --- /dev/null +++ b/container/scripts/argument_sanitizer.sh @@ -0,0 +1,61 @@ +#!/bin/bash + +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT license. +# SPDX-License-Identifier: MIT + +# Exits immediately on failure. +set -eu + +# Function to display usage information +usage() { + echo "Usage: $0 [-a|--arg-value] [-r|--regex] " + echo "Example:" + echo " $0 -a \"\${APP_NAME}\" -r \"^[a-zA-Z_0-9-]+$\"" +} + +# Parse command line arguments +while [[ $# -gt 0 ]] +do + key="$1" + + case $key in + -a|--arg-value) + arg_value="$2" + shift # past argument + shift # past value + ;; + -r|--regex) + regex="$2" + shift # past argument + shift # past value + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Unknown argument: $key" + usage + exit 1 + esac +done + +# Check if all required arguments have been set +if [[ -z "${arg_value}" || -z "${regex}" ]]; then + echo "Error: Missing required arguments:" + [[ -z "${arg_value}" ]] && echo " -a|--arg-value" + [[ -z "${regex}" ]] && echo " -r|--regex" + echo -e "\n" + usage + exit 1 +fi + +sanitized=$(echo "${arg_value}" | tr -dc "${regex}"); +[ "$sanitized" = "${arg_value}" ] || { + echo "ARG is invalid. ARG='${arg_value}' sanitized='${sanitized}'"; + exit 1 +} + +echo -e "\nARG with value '${arg_value}' is sanitized" +exit 0 \ No newline at end of file diff --git a/container/scripts/container_startup.sh b/container/scripts/container_startup.sh new file mode 100755 index 00000000..c5f6350a --- /dev/null +++ b/container/scripts/container_startup.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT license. +# SPDX-License-Identifier: MIT + +# Exits immediately on failure. +set -e + +# Copy any configuration files present to service configuration. +# If there is a configuration file with the same name at `/sdv/config` this will overwrite +# that file with the mounted configuration file. +cp -rf /mnt/config /sdv + +# Start the Ibeji service. +/sdv/service \ No newline at end of file diff --git a/core/common/Cargo.toml b/core/common/Cargo.toml index 8fa85569..e226d4b7 100644 --- a/core/common/Cargo.toml +++ b/core/common/Cargo.toml @@ -35,6 +35,3 @@ url = { workspace = true } [build-dependencies] tonic-build = { workspace = true } - -[features] -containerize = [] diff --git a/core/common/src/utils.rs b/core/common/src/utils.rs index ab732d06..7acfdc03 100644 --- a/core/common/src/utils.rs +++ b/core/common/src/utils.rs @@ -116,10 +116,9 @@ pub async fn discover_service_using_chariott( expected_communication_kind: &str, expected_communication_reference: &str, ) -> Result { - let uri = get_uri(chariott_uri)?; - - let mut client = - ServiceRegistryClient::connect(uri).await.map_err(|e| Status::internal(e.to_string()))?; + let mut client = ServiceRegistryClient::connect(chariott_uri.to_owned()) + .await + .map_err(|e| Status::internal(e.to_string()))?; let request = Request::new(DiscoverRequest { namespace: namespace.to_string(), @@ -183,39 +182,7 @@ pub async fn get_service_uri( } }; - let uri = get_uri(&result)?; - - Ok(uri) -} - -/// If feature 'containerize' is set, will modify a localhost uri to point to container's localhost -/// DNS alias. Otherwise, returns the uri as a String. -/// -/// # Arguments -/// * `uri` - The uri to potentially modify. -pub fn get_uri(uri: &str) -> Result { - #[cfg(feature = "containerize")] - let uri = { - // Container env variable names. - let host_gateway_env_var: &str = "HOST_GATEWAY"; - let host_alias_env_var: &str = "LOCALHOST_ALIAS"; - - // Return an error if container env variables are not set. - let host_gateway = env::var(host_gateway_env_var).map_err(|err| { - Status::failed_precondition(format!( - "Unable to get environment var '{host_gateway_env_var}' with error: {err}" - )) - })?; - let host_alias = env::var(host_alias_env_var).map_err(|err| { - Status::failed_precondition(format!( - "Unable to get environment var '{host_alias_env_var}' with error: {err}" - )) - })?; - - uri.replace(&host_alias, &host_gateway) - }; - - Ok(uri.to_string()) + Ok(result) } #[cfg(test)] diff --git a/core/invehicle-digital-twin/Cargo.toml b/core/invehicle-digital-twin/Cargo.toml index 79509142..213a8bd3 100644 --- a/core/invehicle-digital-twin/Cargo.toml +++ b/core/invehicle-digital-twin/Cargo.toml @@ -39,5 +39,4 @@ tonic-build = { workspace = true } [features] managed_subscribe = ["dep:managed_subscribe"] -containerize = ["common/containerize"] -tokio_console = ["dep:tokio-console-subscriber", "tokio/tracing"] \ No newline at end of file +tokio_console = ["dep:tokio-console-subscriber", "tokio/tracing"] diff --git a/core/invehicle-digital-twin/src/main.rs b/core/invehicle-digital-twin/src/main.rs index 1949c858..bf6f38ed 100644 --- a/core/invehicle-digital-twin/src/main.rs +++ b/core/invehicle-digital-twin/src/main.rs @@ -5,7 +5,6 @@ // Module references behind feature flags. Add any necessary module references here. // Start: Module references. -use common::utils; #[cfg(feature = "managed_subscribe")] use managed_subscribe::managed_subscribe_module::ManagedSubscribeModule; @@ -55,10 +54,9 @@ async fn register_invehicle_digital_twin_service_with_chariott( chariott_uri: &str, invehicle_digital_twin_uri: &str, ) -> Result<(), Status> { - let uri = utils::get_uri(chariott_uri)?; - - let mut client = - ServiceRegistryClient::connect(uri).await.map_err(|e| Status::internal(e.to_string()))?; + let mut client = ServiceRegistryClient::connect(chariott_uri.to_owned()) + .await + .map_err(|e| Status::internal(e.to_string()))?; let service = Some(ServiceMetadata { namespace: INVEHICLE_DIGITAL_TWIN_SERVICE_NAMESPACE.to_string(), diff --git a/core/module/managed_subscribe/Cargo.toml b/core/module/managed_subscribe/Cargo.toml index 81b63cc2..184a9758 100644 --- a/core/module/managed_subscribe/Cargo.toml +++ b/core/module/managed_subscribe/Cargo.toml @@ -27,6 +27,3 @@ yaml-rust = { workspace = true } [build-dependencies] tonic-build = { workspace = true } - -[features] -containerize = ["common/containerize"] diff --git a/core/module/managed_subscribe/src/managed_subscribe_interceptor.rs b/core/module/managed_subscribe/src/managed_subscribe_interceptor.rs index 21edf3cd..3efbc1d2 100644 --- a/core/module/managed_subscribe/src/managed_subscribe_interceptor.rs +++ b/core/module/managed_subscribe/src/managed_subscribe_interceptor.rs @@ -9,7 +9,7 @@ use parking_lot::RwLock; use prost::Message; use std::{collections::HashMap, error::Error, sync::Arc}; -use common::{grpc_interceptor::GrpcInterceptor, utils}; +use common::grpc_interceptor::GrpcInterceptor; use crate::managed_subscribe_store::{CallbackInfo, EntityMetadata, ManagedSubscribeStore}; @@ -77,7 +77,7 @@ impl GrpcInterceptor for ManagedSubscribeInterceptor { for endpoint in &mut endpoints { if endpoint.operations.contains(&Self::MANAGED_SUBSCRIBE_OPERATION.to_string()) { - let entity_callback = utils::get_uri(&endpoint.uri)?; + let entity_callback = endpoint.uri.clone(); let callback_protocol = endpoint.protocol.clone(); // Set endpoint information to the managed subscribe module. diff --git a/samples/Dockerfile.consumer b/samples/Dockerfile.samples.amd64 similarity index 75% rename from samples/Dockerfile.consumer rename to samples/Dockerfile.samples.amd64 index 425a1b30..0b5def23 100644 --- a/samples/Dockerfile.consumer +++ b/samples/Dockerfile.samples.amd64 @@ -10,12 +10,21 @@ # Create a stage for building the application. ARG RUST_VERSION=1.72.1 -FROM docker.io/library/rust:${RUST_VERSION}-slim-bullseye AS build ARG APP_NAME=property-consumer +ARG UID=10001 + +FROM docker.io/library/rust:${RUST_VERSION}-slim-bullseye AS build +ARG APP_NAME WORKDIR /sdv COPY ./ . +# Check that APP_NAME argument is valid. +RUN /sdv/container/scripts/argument_sanitizer.sh \ + --arg-value "${APP_NAME}" \ + --regex "^[a-zA-Z_0-9-]+$" || \ + ( echo "Argument sanitizer failed for ARG 'APP_NAME'"; exit 1 ) + # Add Build dependencies. RUN apt update && apt upgrade -y && apt install -y \ cmake \ @@ -24,15 +33,8 @@ RUN apt update && apt upgrade -y && apt install -y \ pkg-config \ protobuf-compiler -# Check that APP_NAME argument is valid. -RUN sanitized=$(echo "${APP_NAME}" | tr -dc '^[a-zA-Z_0-9-]+$'); \ -[ "$sanitized" = "${APP_NAME}" ] || { \ - echo "ARG 'APP_NAME' is invalid. APP_NAME='${APP_NAME}' sanitized='${sanitized}'"; \ - exit 1; \ -} - -# Build the application with the 'containerize' feature. -RUN cargo build --release --bin "${APP_NAME}" --features "containerize" +# Build the application. +RUN cargo build --release --bin "${APP_NAME}" # Copy the built application to working directory. RUN cp ./target/release/"${APP_NAME}" /sdv/service @@ -49,12 +51,21 @@ RUN cp ./target/release/"${APP_NAME}" /sdv/service # reproducability is important, consider using a digest # (e.g., debian@sha256:ac707220fbd7b67fc19b112cee8170b41a9e97f703f588b2cdbbcdcecdd8af57). FROM docker.io/library/debian:bullseye-slim AS final +ARG UID + +# Copy container scripts. +COPY ./container/scripts/*.sh /sdv/scripts/ + +# Check that UID argument is valid. +RUN /sdv/scripts/argument_sanitizer.sh \ + --arg-value "${UID}" \ + --regex "^[0-9]+$" || \ + ( echo "Argument sanitizer failed for ARG 'UID'"; exit 1 ) RUN apt update && apt upgrade -y && apt install -y libsdl2-dev # Create a non-privileged user that the app will run under. # See https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#user -ARG UID=10001 RUN adduser \ --disabled-password \ --gecos "" \ @@ -63,6 +74,14 @@ RUN adduser \ --no-create-home \ --uid "${UID}" \ appuser + +# Create and add user ownership to config directory. +RUN mkdir -p /sdv/config +RUN chown appuser /sdv/config + +# Create mnt directory to copy override configs into. +RUN mkdir -p /mnt/config + USER appuser WORKDIR /sdv @@ -76,8 +95,5 @@ COPY --from=build /sdv/service /sdv/ # Copy configuration for service. COPY --from=build /sdv/samples/container/config/consumer/ /sdv/config -# Expose the port that the application listens on. -EXPOSE 6010 - # What the container should run when it is started. -CMD ["/sdv/service"] +CMD ["/sdv/scripts/container_startup.sh"] diff --git a/samples/Dockerfile.provider b/samples/Dockerfile.samples.arm64 similarity index 64% rename from samples/Dockerfile.provider rename to samples/Dockerfile.samples.arm64 index 34cad0ca..cc108117 100644 --- a/samples/Dockerfile.provider +++ b/samples/Dockerfile.samples.arm64 @@ -10,32 +10,38 @@ # Create a stage for building the application. ARG RUST_VERSION=1.72.1 +ARG APP_NAME=property-consumer +ARG UID=10001 + FROM docker.io/library/rust:${RUST_VERSION}-slim-bullseye AS build -ARG APP_NAME=property-provider +ARG APP_NAME WORKDIR /sdv COPY ./ . +# Check that APP_NAME argument is valid. +RUN /sdv/container/scripts/argument_sanitizer.sh \ + --arg-value "${APP_NAME}" \ + --regex "^[a-zA-Z_0-9-]+$" || \ + ( echo "Argument sanitizer failed for ARG 'APP_NAME'"; exit 1 ) + # Add Build dependencies. RUN apt update && apt upgrade -y && apt install -y \ cmake \ libsdl2-dev \ libssl-dev \ pkg-config \ - protobuf-compiler + protobuf-compiler \ + gcc-aarch64-linux-gnu \ + g++-aarch64-linux-gnu -# Check that APP_NAME argument is valid. -RUN sanitized=$(echo "${APP_NAME}" | tr -dc '^[a-zA-Z_0-9-]+$'); \ -[ "$sanitized" = "${APP_NAME}" ] || { \ - echo "ARG 'APP_NAME' is invalid. APP_NAME='${APP_NAME}' sanitized='${sanitized}'"; \ - exit 1; \ -} +RUN rustup target add aarch64-unknown-linux-gnu -# Build the application with the 'containerize' feature. -RUN cargo build --release --bin "${APP_NAME}" --features "containerize" +# Build the application. +RUN cargo build --release --target=aarch64-unknown-linux-gnu --bin "${APP_NAME}" # Copy the built application to working directory. -RUN cp ./target/release/"${APP_NAME}" /sdv/service +RUN cp ./target/aarch64-unknown-linux-gnu/release/"${APP_NAME}" /sdv/service ################################################################################ # Create a new stage for running the application that contains the minimal @@ -48,13 +54,20 @@ RUN cp ./target/release/"${APP_NAME}" /sdv/service # most recent version of that tag when you build your Dockerfile. If # reproducability is important, consider using a digest # (e.g., debian@sha256:ac707220fbd7b67fc19b112cee8170b41a9e97f703f588b2cdbbcdcecdd8af57). -FROM docker.io/library/debian:bullseye-slim AS final +FROM docker.io/arm64v8/debian:bullseye-slim AS final +ARG UID + +# Copy container scripts. +COPY ./container/scripts/*.sh /sdv/scripts/ -RUN apt update && apt upgrade -y && apt install -y libsdl2-dev +# Check that UID argument is valid. +RUN /sdv/scripts/argument_sanitizer.sh \ + --arg-value "${UID}" \ + --regex "^[0-9]+$" || \ + ( echo "Argument sanitizer failed for ARG 'UID'"; exit 1 ) # Create a non-privileged user that the app will run under. # See https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#user -ARG UID=10001 RUN adduser \ --disabled-password \ --gecos "" \ @@ -63,6 +76,14 @@ RUN adduser \ --no-create-home \ --uid "${UID}" \ appuser + +# Create and add user ownership to config directory. +RUN mkdir -p /sdv/config +RUN chown appuser /sdv/config + +# Create mnt directory to copy override configs into. +RUN mkdir -p /mnt/config + USER appuser WORKDIR /sdv @@ -74,10 +95,7 @@ ENV IBEJI_HOME=/sdv/config COPY --from=build /sdv/service /sdv/ # Copy configuration for service. -COPY --from=build /sdv/samples/container/config/provider/ /sdv/config - -# Expose the port that the application listens on. -EXPOSE 4010 +COPY --from=build /sdv/samples/container/config/consumer/ /sdv/config # What the container should run when it is started. -CMD ["/sdv/service"] +CMD ["/sdv/scripts/container_startup.sh"] diff --git a/samples/common/.cargo/config.toml b/samples/common/.cargo/config.toml new file mode 100644 index 00000000..47b518be --- /dev/null +++ b/samples/common/.cargo/config.toml @@ -0,0 +1,3 @@ +[target.aarch64-unknown-linux-gnu] +linker = "aarch64-linux-gnu-g++" +rustflags = [ "-C", "target-feature=+crt-static", "-C", "link-arg=-lg++" ] diff --git a/samples/common/Cargo.toml b/samples/common/Cargo.toml index dc5b7659..e398c20b 100644 --- a/samples/common/Cargo.toml +++ b/samples/common/Cargo.toml @@ -20,5 +20,6 @@ tokio = { workspace = true } tonic = { workspace = true } yaml-rust = { workspace = true } -[features] -containerize = [] +# If built for aarch64, enable the 'vendored-ssl' feature. +[target.'cfg(target_arch = "aarch64")'.dependencies] +sdl2 = { workspace = true, features = [ "bundled", "static-link" ] } diff --git a/samples/common/src/utils.rs b/samples/common/src/utils.rs index 0b4ee2f5..f8497f4f 100644 --- a/samples/common/src/utils.rs +++ b/samples/common/src/utils.rs @@ -129,15 +129,12 @@ pub async fn discover_digital_twin_provider_using_ibeji( }) .cloned() { - Some(mut result) => { + Some(result) => { info!( "Found a matching endpoint for entity id {entity_id} that has URI {}", result.uri ); - result.uri = get_uri(&result.uri) - .map_err(|err| format!("Failed to get provider URI due to error: {err}"))?; - Ok(result) } None => Err("Did not find an endpoint that met our requirements".to_string()), @@ -161,10 +158,9 @@ pub async fn discover_service_using_chariott( communication_kind: &str, communication_reference: &str, ) -> Result { - let uri = get_uri(chariott_uri)?; - - let mut client = - ServiceRegistryClient::connect(uri).await.map_err(|e| Status::internal(e.to_string()))?; + let mut client = ServiceRegistryClient::connect(chariott_uri.to_owned()) + .await + .map_err(|e| Status::internal(e.to_string()))?; let request = Request::new(DiscoverRequest { namespace: namespace.to_string(), @@ -233,39 +229,7 @@ pub async fn retrieve_invehicle_digital_twin_uri( } }; - get_uri(&result).map_err(|err| { - format!("Failed to retrieve the in-vehicle digital twin service's URI due to error: {err}") - }) -} - -/// If the 'containerize' feature is set, this function will modify the localhost URI to point to -/// the container's localhost DNS alias. Otherwise, returns the URI as a string. -/// -/// # Arguments -/// * `uri` - The uri to potentially modify. -pub fn get_uri(uri: &str) -> Result { - #[cfg(feature = "containerize")] - let uri = { - // Container env variable names. - let host_gateway_env_var: &str = "HOST_GATEWAY"; - let host_alias_env_var: &str = "LOCALHOST_ALIAS"; - - // Return an error if container env variables are not set. - let host_gateway = std::env::var(host_gateway_env_var).map_err(|err| { - Status::failed_precondition(format!( - "Unable to get environment var '{host_gateway_env_var}' with error: {err}" - )) - })?; - let host_alias = std::env::var(host_alias_env_var).map_err(|err| { - Status::failed_precondition(format!( - "Unable to get environment var '{host_alias_env_var}' with error: {err}" - )) - })?; - - uri.replace(&host_alias, &host_gateway) - }; - - Ok(uri.to_string()) + Ok(result) } #[cfg(test)] diff --git a/samples/container/.accepted_words.txt b/samples/container/.accepted_words.txt deleted file mode 100644 index 49d4301f..00000000 --- a/samples/container/.accepted_words.txt +++ /dev/null @@ -1,93 +0,0 @@ -Agemo -agemo -APP -arg -br -build -cargo -cd -CHARIOTT -Chariott -Chariott's -chariott -com -config -containerize -containerized -Containerization -Ctrl -dev -digitaltwins -dir -Dockerfile -dockerfile -dockerfiles -dotnet -dst -dt -dtdl -DTDL -en -env -fontconfig -gcc -gcc's -github -hardcheese -haudebourg -https -ibeji -Ibeji -Ibeji's -intellectualproperty -invehicle -io -iot -js -json -JSON -kbd -ld -LD -libfontconfig -libsdl -localhost -loopback -md -microsoft -minimalistic -mosquitto -Mosquitto -mqtt -MQTT -netns -opendigitaltwins -plugandplay -Podman -podman -protobuf -Protobuf -ps -repo -Repo -rm -ro -rustup -sdk -sdl -SDL -sdv -slirp -snapd -src -standalone -sudo -timothee -toml -Tonic -toolchain -uri -URI -www -xargs -yaml diff --git a/samples/container/README.md b/samples/container/README.md deleted file mode 100644 index f3467046..00000000 --- a/samples/container/README.md +++ /dev/null @@ -1,157 +0,0 @@ -# Samples Containerization - -This document covers how to containerize the samples for Ibeji. To run the in-vehicle digital twin -service as a container or to get more in depth instruction for building and running a container -please refer to [Ibeji Containerization](../../container/README.md). - -## Running the Samples in a Container - -Below are the steps for running the sample providers and consumers in a container. Note that the -configuration files used by the containerized sample are cloned from -[/samples/container/config](./config/) defined in the project's root. - -### Provider - -Provider containers utilize the dockerfile [Dockerfile.provider](../Dockerfile.provider). - -#### Build - -By default, the sample provider built in the Dockerfile is the -[property-provider](../property/provider/). To change the provider the container builds, use -the following argument: - - Docker - - ```shell - --build-arg APP_NAME={name of the provider} - ``` - - For example: - - ```shell - docker build -t provider -f ./samples/Dockerfile.provider . --build-arg APP_NAME=managed-subscribe-provider - ``` - - Podman - - ```shell - --build-arg=APP_NAME={name of the provider} - ``` - - For example: - - ```shell - podman build -t provider:latest -f ./samples/Dockerfile.provider . --build-arg=APP_NAME=managed-subscribe-provider - ``` - -#### Run - -If you selected a different provider than the default provider built in the dockerfile, you may -need to override the configuration file [provider_settings.yaml](./config/provider/provider_settings.yaml). -To override the configuration of a provider container, follow the below steps after you have built -the container: - - Docker - - 1. To run the container with overridden configuration, create your config file and set an - environment variable called IBEJI_HOME to the absolute path of the directory containing the - config file: - - ```shell - export IBEJI_HOME={absolute path of the directory containing the config file} - ``` - - 1. Then run the container from the project's root with the following command: - - ```shell - docker run -v ${IBEJI_HOME}:/sdv/config --name provider -p 5010:5010 --env-file=./samples/container/config/docker.env --add-host=host.docker.internal:host-gateway -it --rm invehicle_digital_twin - ``` - - Podman - - 1. To run the container with overridden configuration, create your config file and set an - environment variable called IBEJI_HOME to the absolute path of the directory containing the - config file: - - ```shell - export IBEJI_HOME={absolute path of the directory containing the config file} - ``` - - 1. Then run the container from the project's root with the following command: - - ```shell - podman run --mount=type=bind,src=${IBEJI_HOME},dst=/sdv/config,ro=true -p 5010:5010 --env-file=./samples/container/config/podman.env --network=slirp4netns:allow_host_loopback=true localhost/provider:latest - ``` - -### Consumer - -Consumer containers utilize the dockerfile [Dockerfile.consumer](../Dockerfile.consumer). - -#### Build - -By default, the sample consumer built in the Dockerfile is the -[property-consumer](../property/consumer/). To change the consumer the container builds, use -the following argument: - - Docker - - ```shell - --build-arg APP_NAME={name of the consumer} - ``` - - For example: - - ```shell - docker build -t consumer -f ./samples/Dockerfile.consumer . --build-arg APP_NAME=managed-subscribe-consumer - ``` - - Podman - - ```shell - --build-arg=APP_NAME={name of the consumer} - ``` - - For example: - - ```shell - podman build -t consumer:latest -f ./samples/Dockerfile.consumer . --build-arg=APP_NAME=managed-subscribe-consumer - ``` - -#### Run - -If you selected a different consumer than the default consumer built in the dockerfile, you may -need to override the configuration file [consumer_settings.yaml](./config/consumer/consumer_settings.yaml). -To override the configuration of a consumer container, follow the below steps after you have built -the container: - - Docker - - 1. To run the container with overridden configuration, create your config file and set an - environment variable called IBEJI_HOME to the absolute path of the directory containing the - config file: - - ```shell - export IBEJI_HOME={absolute path of the directory containing the config file} - ``` - - 1. Then run the container from the project's root with the following command: - - ```shell - docker run -v ${IBEJI_HOME}:/sdv/config --name consumer -p 5010:5010 --env-file=./samples/container/config/docker.env --add-host=host.docker.internal:host-gateway -it --rm invehicle_digital_twin - ``` - - Podman - - 1. To run the container with overridden configuration, create your config file and set an - environment variable called IBEJI_HOME to the absolute path of the directory containing the - config file: - - ```shell - export IBEJI_HOME={absolute path of the directory containing the config file} - ``` - - 1. Then run the container from the project's root with the following command: - - ```shell - podman run --mount=type=bind,src=${IBEJI_HOME},dst=/sdv/config,ro=true -p 5010:5010 --env-file=./samples/container/config/podman.env --network=slirp4netns:allow_host_loopback=true localhost/consumer:latest - ``` diff --git a/samples/container/config/docker.env b/samples/container/config/docker.env deleted file mode 100644 index 56bafc6e..00000000 --- a/samples/container/config/docker.env +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT license. -# SPDX-License-Identifier: MIT - -# DNS name used by the container to communicate with host. -HOST_GATEWAY=host.docker.internal - -# Alias for localhost to be replaced by HOST_GATEWAY if run in a container. -LOCALHOST_ALIAS=0.0.0.0 diff --git a/samples/container/config/podman.env b/samples/container/config/podman.env deleted file mode 100644 index 1abc4a35..00000000 --- a/samples/container/config/podman.env +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT license. -# SPDX-License-Identifier: MIT - -# DNS name used by the container to communicate with host. -HOST_GATEWAY=host.containers.internal - -# Alias for localhost to be replaced by HOST_GATEWAY if run in a container. -LOCALHOST_ALIAS=0.0.0.0 diff --git a/samples/managed_subscribe/Cargo.toml b/samples/managed_subscribe/Cargo.toml index f82adb36..63ed3e7d 100644 --- a/samples/managed_subscribe/Cargo.toml +++ b/samples/managed_subscribe/Cargo.toml @@ -39,5 +39,6 @@ path = "provider/src/main.rs" name = "managed-subscribe-consumer" path = "consumer/src/main.rs" -[features] -containerize = ["samples-common/containerize"] +# If built for aarch64, enable the 'vendored-ssl' feature. +[target.'cfg(target_arch = "aarch64")'.dependencies] +paho-mqtt = { workspace = true, features = ["vendored-ssl"] } diff --git a/samples/managed_subscribe/consumer/src/main.rs b/samples/managed_subscribe/consumer/src/main.rs index e8ec255d..44b467a5 100644 --- a/samples/managed_subscribe/consumer/src/main.rs +++ b/samples/managed_subscribe/consumer/src/main.rs @@ -11,7 +11,7 @@ use paho_mqtt as mqtt; use samples_common::constants::{constraint_type, digital_twin_operation, digital_twin_protocol}; use samples_common::consumer_config; use samples_common::utils::{ - discover_digital_twin_provider_using_ibeji, get_uri, retrieve_invehicle_digital_twin_uri, + discover_digital_twin_provider_using_ibeji, retrieve_invehicle_digital_twin_uri, }; use samples_protobuf_data_access::module::managed_subscribe::v1::managed_subscribe_client::ManagedSubscribeClient; use samples_protobuf_data_access::module::managed_subscribe::v1::{ @@ -180,7 +180,7 @@ async fn main() -> Result<(), Box> { .await?; // Deconstruct subscription information. - let broker_uri = get_uri(&subscription_info.uri)?; + let broker_uri = subscription_info.uri; let topic = subscription_info.context; info!("The broker URI for the AmbientAirTemperature property's provider is {broker_uri}"); diff --git a/samples/managed_subscribe/provider/src/provider_impl.rs b/samples/managed_subscribe/provider/src/provider_impl.rs index 9fe889a4..a0151042 100644 --- a/samples/managed_subscribe/provider/src/provider_impl.rs +++ b/samples/managed_subscribe/provider/src/provider_impl.rs @@ -16,7 +16,6 @@ use log::{debug, info, warn}; use paho_mqtt as mqtt; use parking_lot::RwLock; use samples_common::constants::constraint_type; -use samples_common::utils; use serde_derive::{Deserialize, Serialize}; use strum_macros::{Display, EnumString}; use tokio::sync::{mpsc, watch}; @@ -131,9 +130,7 @@ impl ProviderImpl { let min_interval_ms = self.min_interval_ms; // This should not be empty. - let mut subscription_info = payload.subscription_info.unwrap(); - - subscription_info.uri = utils::get_uri(&subscription_info.uri).unwrap(); + let subscription_info = payload.subscription_info.unwrap(); // Create stop publish channel. let (sender, mut reciever) = mpsc::channel(10); diff --git a/samples/property/Cargo.toml b/samples/property/Cargo.toml index e24508d1..fe7b9743 100644 --- a/samples/property/Cargo.toml +++ b/samples/property/Cargo.toml @@ -37,5 +37,6 @@ path = "provider/src/main.rs" name = "property-consumer" path = "consumer/src/main.rs" -[features] -containerize = ["samples-common/containerize"] +# If built for aarch64, enable the 'vendored-ssl' feature. +[target.'cfg(target_arch = "aarch64")'.dependencies] +paho-mqtt = { workspace = true, features = ["vendored-ssl"] } diff --git a/samples/property/provider/src/main.rs b/samples/property/provider/src/main.rs index 0808174a..21f9c052 100644 --- a/samples/property/provider/src/main.rs +++ b/samples/property/provider/src/main.rs @@ -8,9 +8,7 @@ use log::{debug, info, warn, LevelFilter}; use paho_mqtt as mqtt; use samples_common::constants::{digital_twin_operation, digital_twin_protocol}; use samples_common::provider_config; -use samples_common::utils::{ - get_uri, retrieve_invehicle_digital_twin_uri, retry_async_based_on_status, -}; +use samples_common::utils::{retrieve_invehicle_digital_twin_uri, retry_async_based_on_status}; use samples_protobuf_data_access::invehicle_digital_twin::v1::invehicle_digital_twin_client::InvehicleDigitalTwinClient; use samples_protobuf_data_access::invehicle_digital_twin::v1::{ EndpointInfo, EntityAccessInfo, RegisterRequest, @@ -209,9 +207,7 @@ async fn main() -> Result<(), Box> { }) .await?; - let stream_uri = get_uri(&broker_uri)?; - - start_ambient_air_temperature_data_stream(stream_uri, topic); + start_ambient_air_temperature_data_stream(broker_uri, topic); signal::ctrl_c().await.expect("Failed to listen for control-c event"); diff --git a/samples/streaming/.cargo/config.toml b/samples/streaming/.cargo/config.toml new file mode 100644 index 00000000..47b518be --- /dev/null +++ b/samples/streaming/.cargo/config.toml @@ -0,0 +1,3 @@ +[target.aarch64-unknown-linux-gnu] +linker = "aarch64-linux-gnu-g++" +rustflags = [ "-C", "target-feature=+crt-static", "-C", "link-arg=-lg++" ] diff --git a/samples/streaming/Cargo.toml b/samples/streaming/Cargo.toml index 1a1b8b41..431917a8 100644 --- a/samples/streaming/Cargo.toml +++ b/samples/streaming/Cargo.toml @@ -45,3 +45,7 @@ path = "provider/src/main.rs" [[bin]] name = "streaming-consumer" path = "consumer/src/main.rs" + +# If built for aarch64, enable the 'vendored-ssl' feature. +[target.'cfg(target_arch = "aarch64")'.dependencies] +sdl2 = { workspace = true, features = [ "bundled", "static-link" ] }