From d7181db0f07efc3a65a77758e12e5d94c82715ec Mon Sep 17 00:00:00 2001 From: Fritz Leo Ochsmann <53190645+Randoooom@users.noreply.github.com> Date: Tue, 9 Jul 2024 17:24:39 +0200 Subject: [PATCH 1/4] refactor: add helm tests --- .dockerignore | 1 - .github/workflows/nightly.yml | 23 ++++++++++++++++ .github/workflows/release.yml | 23 ++++++++++++++++ Cargo.lock | 26 +++++++++++++++++++ Cargo.toml | 13 +++++----- Makefile.toml | 2 +- build.rs | 4 --- charts/feedback-fusion/Chart.yaml | 2 +- .../templates/tests/integration-tests.yaml | 16 ++++++++++++ charts/feedback-fusion/values.yaml | 11 +++++--- tests/common.rs | 17 +++++++----- tests/integration/Dockerfile | 22 ++++++++++++++++ tests/integration/authentication.rs | 2 +- 13 files changed, 138 insertions(+), 24 deletions(-) delete mode 100644 build.rs create mode 100644 charts/feedback-fusion/templates/tests/integration-tests.yaml create mode 100644 tests/integration/Dockerfile diff --git a/.dockerignore b/.dockerignore index 0a2e8bee..7c90671e 100644 --- a/.dockerignore +++ b/.dockerignore @@ -4,6 +4,5 @@ lib/ target/ common/target/ codegen/target/ -tests/ docs/ Makefile.toml diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index ce34a474..84f19f76 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -125,6 +125,29 @@ jobs: push: true tags: ghcr.io/onelitefeathernet/feedback-fusion:nightly + integration: + needs: [docker] + name: dockerize integration test + runs-on: ubuntu-latest + steps: + - name: Checkout Sources + uses: actions/checkout@v4 + + - name: Login into repository + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push Docker image + uses: docker/build-push-action@v6 + with: + context: . + push: true + dockerfile: tests/integration/Dockerfile + tags: ghcr.io/onelitefeathernet/feedback-fusion-integration:nightly + docs: needs: [docker] name: docs diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fc6fd5e3..b85d3348 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -130,6 +130,29 @@ jobs: push: true tags: ghcr.io/onelitefeathernet/feedback-fusion:${{env.VERSION}},ghcr.io/onelitefeathernet/feedback-fusion:latest + integration: + needs: [docker] + name: dockerize integration test + runs-on: ubuntu-latest + steps: + - name: Checkout Sources + uses: actions/checkout@v4 + + - name: Login into repository + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push Docker image + uses: docker/build-push-action@v6 + with: + context: . + push: true + dockerfile: tests/integration/Dockerfile + tags: ghcr.io/onelitefeathernet/feedback-fusion-integration:${{env.VERSION}},ghcr.io/onelitefeathernet/feedback-fusion-integration:latest + docs: needs: [docker] name: docs diff --git a/Cargo.lock b/Cargo.lock index 7c4e617d..7d70bc4a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -615,6 +615,21 @@ dependencies = [ "libc", ] +[[package]] +name = "crossbeam-channel" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + [[package]] name = "crypto-bigint" version = "0.5.5" @@ -1174,6 +1189,15 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fsevent-sys" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" +dependencies = [ + "libc", +] + [[package]] name = "funty" version = "2.0.0" @@ -1957,7 +1981,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" dependencies = [ "bitflags 2.6.0", + "crossbeam-channel", "filetime", + "fsevent-sys", "inotify", "kqueue", "libc", diff --git a/Cargo.toml b/Cargo.toml index 144173eb..dcea1218 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,12 +24,12 @@ kanal = "0.1.0-pre8" lazy_static = "1.4.0" log = "0.4.22" nanoid = "0.4.0" -notify = { version = "6.1.1", default-features = false, features = [ - "macos_kqueue", -] } +notify = "6.1.1" openidconnect = "3.5.0" opentelemetry = { version = "0.23.0", optional = true } -opentelemetry_sdk = { version = "0.23.0", optional = true, features = ["rt-tokio"] } +opentelemetry_sdk = { version = "0.23.0", optional = true, features = [ + "rt-tokio", +] } opentelemetry-otlp = { version = "0.16.0", optional = true } opentelemetry-semantic-conventions = { version = "0.15.0", optional = true } opentelemetry-http = { version = "0.12.0", optional = true } @@ -61,6 +61,7 @@ validator = { version = "0.18", features = ["derive"] } version-compare = "0.2.0" [dev-dependencies] +lazy_static = "1.4.0" paste = "1.0.14" rand = "0.8.5" reqwest = { version = "0.12.3", features = ["json"] } @@ -74,8 +75,8 @@ otlp = [ "opentelemetry-otlp", "opentelemetry-semantic-conventions", "opentelemetry_sdk", - "opentelemetry-http", - "tracing-opentelemetry" + "opentelemetry-http", + "tracing-opentelemetry", ] all-databases = ["postgres", "mysql", "mssql"] postgres = ["rbdc-pg"] diff --git a/Makefile.toml b/Makefile.toml index e6990496..748dee92 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -70,7 +70,7 @@ dependencies = ["docker_network"] script = "docker compose -f tests/_common/oidc-mock/docker-compose.yaml up -d && sleep 5 && curl -s -o /dev/null http://localhost:5151/.well-known/openid-configuration" [tasks.integration_test] -env = { OIDC_PROVIDER = "http://localhost:5151", OIDC_CLIENT_ID = "client", OIDC_CLIENT_SECRET = "secret", RUST_LOG = "INFO" } +env = { OIDC_PROVIDER = "http://localhost:5151", OIDC_CLIENT_ID = "client", OIDC_CLIENT_SECRET = "secret", RUST_LOG = "INFO", GRPC_ENDPOINT = "http://localhost:8000" } command = "cargo" args = ["test", "--no-fail-fast", "--test", "integration_test"] diff --git a/build.rs b/build.rs deleted file mode 100644 index 2770ed24..00000000 --- a/build.rs +++ /dev/null @@ -1,4 +0,0 @@ -// just placeholder to get OUT_DIR - -fn main() {} - diff --git a/charts/feedback-fusion/Chart.yaml b/charts/feedback-fusion/Chart.yaml index 480664f1..f7a18c1f 100644 --- a/charts/feedback-fusion/Chart.yaml +++ b/charts/feedback-fusion/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.5 +version: 0.1.6 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/charts/feedback-fusion/templates/tests/integration-tests.yaml b/charts/feedback-fusion/templates/tests/integration-tests.yaml new file mode 100644 index 00000000..827722f9 --- /dev/null +++ b/charts/feedback-fusion/templates/tests/integration-tests.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "feedback-fusion.fullname" . }}-integration-tests" + labels: + {{- include "feedback-fusion.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: integration-tests + image: "{{ .Values.image.testRepository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + envFrom: + - secretRef: + name: {{ .Values.feedbackFusion.testSecret }} + restartPolicy: Never diff --git a/charts/feedback-fusion/values.yaml b/charts/feedback-fusion/values.yaml index 603a71bb..021cdec0 100644 --- a/charts/feedback-fusion/values.yaml +++ b/charts/feedback-fusion/values.yaml @@ -2,6 +2,7 @@ replicaCount: 1 image: repository: ghcr.io/onelitefeathernet/feedback-fusion + testRepository: ghcr.io/onelitefeathernet/feedback-fusion-integration pullPolicy: IfNotPresent # Overrides the image tag whose default is the chart appVersion. tag: "" @@ -45,10 +46,10 @@ ingress: # kubernetes.io/ingress.class: nginx # kubernetes.io/tls-acme: "true" hosts: - - host: chart-example.local - paths: - - path: / - pathType: ImplementationSpecific + # - host: chart-example.local + # paths: + # - path: / + # pathType: ImplementationSpecific tls: [] # - secretName: chart-example-tls # hosts: @@ -139,4 +140,6 @@ feedbackFusion: # MSSQL_DATABASE: "" # MSSQL_ENCRYPT: true # MSSQL_TRUST_SERVER_CERTIFICATE: true + + testSecret: feedback-fusion-integration-test diff --git a/tests/common.rs b/tests/common.rs index 071e2e5d..e0878155 100644 --- a/tests/common.rs +++ b/tests/common.rs @@ -20,24 +20,29 @@ //DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +use lazy_static::lazy_static; use openidconnect::{ core::{CoreClient, CoreProviderMetadata}, reqwest::async_http_client, ClientId, ClientSecret, IssuerUrl, OAuth2TokenResponse, Scope, }; -pub const GRPC_ENDPOINT: &str = "http://localhost:8000"; +lazy_static! { + pub static ref GRPC_ENDPOINT: String = std::env::var("GRPC_ENDPOINT").unwrap(); +} #[allow(unused)] pub async fn authenticate() -> String { - let issuer = IssuerUrl::new(env!("OIDC_PROVIDER").to_owned()).unwrap(); + let issuer = IssuerUrl::new(std::env::var("OIDC_PROVIDER").unwrap()).unwrap(); let metadata = CoreProviderMetadata::discover_async(issuer, async_http_client) .await .unwrap(); let client = CoreClient::from_provider_metadata( metadata, - ClientId::new(env!("OIDC_CLIENT_ID").to_owned()), - Some(ClientSecret::new(env!("OIDC_CLIENT_SECRET").to_owned())), + ClientId::new(std::env::var("OIDC_CLIENT_ID").unwrap()), + Some(ClientSecret::new( + std::env::var("OIDC_CLIENT_SECRET").unwrap(), + )), ); let token_response = client @@ -53,7 +58,7 @@ pub async fn authenticate() -> String { #[macro_export] macro_rules! connect { () => {{ - let channel = tonic::transport::Channel::from_static(crate::common::GRPC_ENDPOINT).connect().await.unwrap(); + let channel = tonic::transport::Channel::from_static(&crate::common::GRPC_ENDPOINT).connect().await.unwrap(); let token: tonic::metadata::MetadataValue<_> = format!("Bearer {}", crate::common::authenticate().await).parse().unwrap(); let client = @@ -65,7 +70,7 @@ macro_rules! connect { Ok(request) }); - let public_client = feedback_fusion_common::proto::public_feedback_fusion_v1_client::PublicFeedbackFusionV1Client::connect(crate::common::GRPC_ENDPOINT) + let public_client = feedback_fusion_common::proto::public_feedback_fusion_v1_client::PublicFeedbackFusionV1Client::connect(crate::common::GRPC_ENDPOINT.as_str()) .await .unwrap(); diff --git a/tests/integration/Dockerfile b/tests/integration/Dockerfile new file mode 100644 index 00000000..3937c5b8 --- /dev/null +++ b/tests/integration/Dockerfile @@ -0,0 +1,22 @@ +FROM rust:slim as build + +COPY ./Cargo.toml . +COPY ./Cargo.lock . +COPY ./proto ./proto +COPY ./common ./common +COPY ./codegen ./codegen +COPY ./src ./src +COPY ./tests ./tests +COPY ./rust-toolchain.toml . + +RUN apt-get update \ + && apt-get install libssl-dev protobuf-compiler libprotobuf-dev pkg-config -y --no-install-recommends \ + && apt-get clean\ + && cargo test --no-run --test integration_test \ + && rm target/debug/deps/integration_test*.d + +FROM gcr.io/distroless/cc-debian12 + +COPY --from=build ./target/debug/deps/integration_test* ./integration_test + +ENTRYPOINT ["./integration_test"] diff --git a/tests/integration/authentication.rs b/tests/integration/authentication.rs index 32eb8e1c..dd1f6a55 100644 --- a/tests/integration/authentication.rs +++ b/tests/integration/authentication.rs @@ -34,7 +34,7 @@ macro_rules! test_authentication { paste::paste! { #[test(tokio::test)] async fn []() { - let mut client = FeedbackFusionV1Client::connect(crate::common::GRPC_ENDPOINT) + let mut client = FeedbackFusionV1Client::connect(crate::common::GRPC_ENDPOINT.as_str()) .await .unwrap(); From b5522f3769ae808d1c70ee1097a648b51a1fe9ba Mon Sep 17 00:00:00 2001 From: Fritz Leo Ochsmann <53190645+Randoooom@users.noreply.github.com> Date: Tue, 9 Jul 2024 17:35:04 +0200 Subject: [PATCH 2/4] ci: build tests with release target --- tests/integration/Dockerfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/integration/Dockerfile b/tests/integration/Dockerfile index 3937c5b8..feb08964 100644 --- a/tests/integration/Dockerfile +++ b/tests/integration/Dockerfile @@ -12,11 +12,11 @@ COPY ./rust-toolchain.toml . RUN apt-get update \ && apt-get install libssl-dev protobuf-compiler libprotobuf-dev pkg-config -y --no-install-recommends \ && apt-get clean\ - && cargo test --no-run --test integration_test \ - && rm target/debug/deps/integration_test*.d + && cargo test --release --no-run --test integration_test \ + && rm target/release/deps/integration_test*.d FROM gcr.io/distroless/cc-debian12 -COPY --from=build ./target/debug/deps/integration_test* ./integration_test +COPY --from=build ./target/release/deps/integration_test* ./integration_test ENTRYPOINT ["./integration_test"] From 6391ee4d43a3cc540d4b512aaa4b64208b18bc16 Mon Sep 17 00:00:00 2001 From: Fritz Leo Ochsmann <53190645+Randoooom@users.noreply.github.com> Date: Tue, 9 Jul 2024 17:37:05 +0200 Subject: [PATCH 3/4] chore: bump --- Cargo.lock | 2 +- Cargo.toml | 2 +- charts/feedback-fusion/Chart.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7d70bc4a..7479a234 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1035,7 +1035,7 @@ checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "feedback-fusion" -version = "0.1.3" +version = "0.1.4" dependencies = [ "aliri", "aliri_clock", diff --git a/Cargo.toml b/Cargo.toml index dcea1218..db6ecbfa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "feedback-fusion" -version = "0.1.3" +version = "0.1.4" edition = "2021" license = "MIT" diff --git a/charts/feedback-fusion/Chart.yaml b/charts/feedback-fusion/Chart.yaml index f7a18c1f..78d02ff0 100644 --- a/charts/feedback-fusion/Chart.yaml +++ b/charts/feedback-fusion/Chart.yaml @@ -21,4 +21,4 @@ version: 0.1.6 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: "0.1.3" +appVersion: "0.1.4" From f5a004b5b4f1596137b942b20142d51f4a4730ef Mon Sep 17 00:00:00 2001 From: Fritz Leo Ochsmann <53190645+Randoooom@users.noreply.github.com> Date: Tue, 9 Jul 2024 17:52:43 +0200 Subject: [PATCH 4/4] chore: docs --- docs/.vitepress/config.ts | 3 +-- docs/docs/deployment/docker.md | 29 +++++++++++++++++++++++++++ docs/docs/deployment/helm.md | 36 ++++++++++++++++++++++++++++++++++ docs/docs/deployment/verify.md | 20 ------------------- 4 files changed, 66 insertions(+), 22 deletions(-) delete mode 100644 docs/docs/deployment/verify.md diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index c781472f..baa9beaf 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -20,8 +20,7 @@ export default defineConfig({ { text: "Deployment", items: [ { text: "Helm", link: "/docs/deployment/helm" }, - { text: "Docker", link: "/docs/deployment/docker" }, - { text: "Verify deployment", link: "/docs/deployment/verify" } + { text: "Docker", link: "/docs/deployment/docker" } ] }, { diff --git a/docs/docs/deployment/docker.md b/docs/docs/deployment/docker.md index 1231acde..3d8b5de9 100644 --- a/docs/docs/deployment/docker.md +++ b/docs/docs/deployment/docker.md @@ -30,3 +30,32 @@ Afterwards start the application: ```sh docker compose up -d ``` + +## Verifying Deployment + +To verify your deployment you can now run the dockerized integration tests using `ghcr.io/onelitefeathernet/feedback-fusion-integrtion:`. +The image requires the following environment variables to be set: + +| Key | Description | +|-----------------|-----------------------------------------------------| +| OIDC_PROVIDER | URL of the OIDC provider | +| OIDC_CLIENT_ID | The client ID | +| OIDC_CLIENT_SECRET | The client secret | +| GRPC_ENDPOINT | The endpoint of the deployed application | + +### Run the tests + +```sh +docker run --network \ + -e OIDC_PROVIDER= \ + -e OIDC_CLIENT_ID= \ + -e OIDC_CLIENT_SECRET= \ + -e GRPC_ENDPOINT= + --name feedback-fusion-integration-test \ + --rm \ + ghcr.io/onelitefeathernet/feedback-fusion-integrtion: +``` + +### On finish + +You should now reset your database as the integration test does not delete everything it created. diff --git a/docs/docs/deployment/helm.md b/docs/docs/deployment/helm.md index 2c48da90..6890de6e 100644 --- a/docs/docs/deployment/helm.md +++ b/docs/docs/deployment/helm.md @@ -60,6 +60,7 @@ Refer to the [configuration documentation](/docs/configuration) for the fields t | `feedbackFusion.preset.create` | Create preset configuration | `false` | | `feedbackFusion.preset.data` | Preset data | `{}` [Preset configuration](/docs/configuration#presets) | | `feedbackFusion.config.secret` | Name of the secret containing configuration | `feedback-fusion-config` | +| `feedbackFusion.testSecret` | Name of the secret containing configuration for the integration test | `feedback-fusion-integration-test` | ## Install @@ -68,3 +69,38 @@ helm install feedback-fusion feedback-fusion/feedback-fusion --wait --atomic ``` Your instance should now be up and running :) + +## Verifying Deployment with Helm Test + +To verify the deployment of the Helm chart, you can use the `helm test` command. However, before running the test, a secret must be created with the name `feedback-fusion-integration-test`. Alternatively, the name of another secret can be set via the Helm value `feedbackFusion.testSecret`. + +The secret should contain the following values: + +| Key | Description | +|-----------------|-----------------------------------------------------| +| OIDC_PROVIDER | URL of the OIDC provider | +| OIDC_CLIENT_ID | The client ID | +| OIDC_CLIENT_SECRET | The client secret | +| GRPC_ENDPOINT | The endpoint of the deployed application | + +### Creating the Secret + +To create the secret, you can use the following `kubectl` command: + +```sh +kubectl create -n secret generic feedback-fusion-integration-test \ + --from-literal=OIDC_PROVIDER= \ + --from-literal=OIDC_CLIENT_ID= \ + --from-literal=OIDC_CLIENT_SECRET= \ + --from-literal=GRPC_ENDPOINT= +``` + +### Run the tests + +```sh +helm test -n +``` + +### On finish + +You should now reset your database as the integration test does not delete everything it created. diff --git a/docs/docs/deployment/verify.md b/docs/docs/deployment/verify.md deleted file mode 100644 index 7ab759a8..00000000 --- a/docs/docs/deployment/verify.md +++ /dev/null @@ -1,20 +0,0 @@ -# Verify the deployment - -To verify and test the deployment of FeedbackFusion, you can run the integration tests. The following prerequisites and instructions will guide you through the process. - -## Prerequisites - -- **Rust** installed on your machine. -- **cargo-make** installed. You can install it using the following command: - ```sh - cargo install cargo-make - ``` -- The FeedbackFusion application must be accessible on port 8000 on the machine where the tests are executed. This can be achieved via port-forwarding if using Kubernetes. -- Override the `OIDC_PROVIDER`, `CLIENT_ID` and `CLIENT_SECRET` in the Makefile. - -## Running Integration Tests - -To run the integration tests, execute the following command: - -```sh -cargo make integration_test