From 83246cbf6d87ffc689aa0ee2f82ea388c37ea229 Mon Sep 17 00:00:00 2001 From: Neil-Jocelyn Schark <neil.schark@h-da.de> Date: Fri, 1 Dec 2023 13:44:47 +0000 Subject: [PATCH] Create new integration-test setup See merge request danet/gosdn!574 Co-authored-by: Malte Bauch <malte.bauch@stud.h-da.de> Co-authored-by: Fabian Seidl <fabian.seidl@h-da.de> --- .devcontainer/Dockerfile | 11 +- .devcontainer/devcontainer.json | 6 +- .dockerignore | 1 - .gitignore | 6 +- .gitlab-ci.yml | 19 +- .gitlab/ci/.build-container-images.yml | 71 ++- .gitlab/ci/.code-quality-ci.yml | 2 +- .gitlab/ci/.integration-test.yml | 33 -- .gitlab/ci/.test.yml | 63 +- .gitlab/ci/gnmi-cert-integration.Dockerfile | 8 + .gitlab/ci/gosdn-integration.Dockerfile | 10 + .../.integration-test-containerlab.yml | 15 +- .gitlab/ci/legacy/.integration-test.yml | 32 + .gitlab/ci/legacy/.test.yml | 33 ++ Makefile | 30 +- README.md | 24 +- .../arista-routing-engine.Dockerfile | 2 +- .../venv-manager/venv-manager.Dockerfile | 2 +- .../venv-manager/venv-manager/venv-manager.go | 2 +- applications/ws-events/ws-events.Dockerfile | 2 +- controller/Makefile | 22 +- controller/api/apiIntegration_test.go | 146 ----- controller/api/initialise_test.go | 2 - controller/cmd/root.go | 4 +- .../configs/integration-test-gosdn.toml | 21 + controller/controller.Dockerfile | 10 +- controller/controller.Dockerfile.dockerignore | 4 +- .../server/configurationmanagement.go | 5 +- .../integration/nucleusIntegration_test.go | 556 ------------------ dev_env_data/clab/basic_two_gnmi_targets.yaml | 24 + dev_env_data/clab/demo.clab.yaml | 6 +- dev_env_data/clab/gosdn.clab.yaml | 2 +- .../integration-test_docker-compose.yml | 53 ++ .../example_tests/controller_test.go | 19 + .../integrationTestUtils.go | 72 +++ mkdocs.yml | 4 +- plugin-registry/plugin-registry.Dockerfile | 2 +- .../plugin-registry.Dockerfile.dockerignore | 3 +- 38 files changed, 453 insertions(+), 874 deletions(-) delete mode 100644 .gitlab/ci/.integration-test.yml create mode 100644 .gitlab/ci/gnmi-cert-integration.Dockerfile create mode 100644 .gitlab/ci/gosdn-integration.Dockerfile rename .gitlab/ci/{ => legacy}/.integration-test-containerlab.yml (92%) create mode 100644 .gitlab/ci/legacy/.integration-test.yml create mode 100644 .gitlab/ci/legacy/.test.yml delete mode 100644 controller/api/apiIntegration_test.go create mode 100644 controller/configs/integration-test-gosdn.toml delete mode 100644 controller/test/integration/nucleusIntegration_test.go create mode 100644 dev_env_data/clab/basic_two_gnmi_targets.yaml create mode 100644 dev_env_data/docker-compose/integration-test_docker-compose.yml create mode 100644 integration-tests/example_tests/controller_test.go create mode 100644 integration-tests/integrationTestUtils/integrationTestUtils.go diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 74cbf443a..811bc1b83 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,4 +1,4 @@ -# The devcontainer will be based on Python +# The devcontainer will be based on debian # The base container already has entrypoint, vscode user account, etc. out of the box FROM mcr.microsoft.com/vscode/devcontainers/base:bullseye @@ -6,17 +6,17 @@ FROM mcr.microsoft.com/vscode/devcontainers/base:bullseye ARG _CLAB_VERSION # Set permissions for mounts in devcontainer.json -RUN mkdir /home/vscode/.vscode-server/ -RUN mkdir /home/vscode/.vscode-server/bin +RUN mkdir -p /home/vscode/.vscode-server/bin RUN chown -R vscode:vscode /home/vscode/.vscode-server # Update and install some basic tools inside the container # Adjust this list based on your demands RUN apt-get update \ && apt-get upgrade -y \ - && apt-get install -y --no-install-recommends \ + && apt-get install -y \ sshpass \ curl \ + wget \ iputils-ping \ htop \ zsh \ @@ -29,7 +29,7 @@ RUN apt-get update \ && rm -Rf /usr/share/doc && rm -Rf /usr/share/man \ && apt-get clean -# Install oh-my-zsh for more terminal features and set is as primary shell +# Install oh-my-zsh for more terminal features and set it as primary shell ENV SHELL /bin/zsh RUN wget https://github.com/robbyrussell/oh-my-zsh/raw/master/tools/install.sh -O - | zsh || true @@ -39,4 +39,3 @@ RUN echo "export EDITOR='nano'" >> /home/vscode/.zshrc # Install preferred version of the containerlab RUN bash -c "$(curl -sL https://get.containerlab.dev)" -- -v ${_CLAB_VERSION} - #&& pip3 install --user yamllint diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 7c93425e6..887b52a5d 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,11 +1,11 @@ // For format details, see https://aka.ms/devcontainer.json. For config options, see the - // README at: https://github.com/devcontainers/templates/tree/main/src/python +// README at: https://github.com/devcontainers/templates/tree/main/src/python { "name": "goSDN-develop-clab-go", "build": { "dockerfile": "Dockerfile", "args": { - "_CLAB_VERSION": "0.47.2" + "_CLAB_VERSION": "0.48.6" } }, "features": { @@ -16,7 +16,7 @@ }, "ghcr.io/devcontainers/features/go:1": { "version": "1.21" - } + } }, // Add any required extensions that must be pre-installed in the devcontainer "customizations": { diff --git a/.dockerignore b/.dockerignore index a6d07de06..0b61b6ba7 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,5 +1,4 @@ .git -.gitlab build documentation mocks diff --git a/.gitignore b/.gitignore index ea0772adf..bdaaaa30d 100644 --- a/.gitignore +++ b/.gitignore @@ -4,8 +4,8 @@ artifacts/ # containerlab clab-gosdn*/ -*clab.yml.bak -dev_env_data/clab/*clab.yaml.bak +*.yml.bak +dev_env_data/clab/*.yaml.bak # non vimmers .vscode/ @@ -74,4 +74,4 @@ plugin-registry/plugins/ # lab-vm lab-vm/vm-with-packer/VM/ -lab-vm/vm-with-vagrant/.vagrant/ \ No newline at end of file +lab-vm/vm-with-vagrant/.vagrant/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2ea8eb57a..7d116ad58 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,8 +1,13 @@ variables: - GOSDN_IMAGE: "${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHA}" - GOSDN_TESTING_IMAGE: "${CI_REGISTRY_IMAGE}:testing_${CI_COMMIT_SHA}" + DOCKER_TAG: $CI_COMMIT_SHA + GOSDN_IMAGE: "${CI_REGISTRY_IMAGE}:${DOCKER_TAG}" + GOSDN_TESTING_IMAGE: "${CI_REGISTRY_IMAGE}:testing_${DOCKER_TAG}" + GOSDN_INTEGRATION_TEST_IMAGE: "${CI_REGISTRY_IMAGE}/integration-tests:${DOCKER_TAG}" CEOS_IMAGE: "${CI_PCONTAINERS_REGISTRY_IMAGE}/ceos:4.28.2F" + CLAB_VERSION: "0.48.6" GOLANG_VERSION: "1.21" + GNMI_TARGET_IMAGE: registry.code.fbi.h-da.de/danet/gnmi-target/debian:master + GNMI_TARGET_INTEGRATION_IMAGE: "registry.code.fbi.h-da.de/danet/gosdn/gnmi-target-integration-test:${CI_COMMIT_SHA}" workflow: rules: @@ -12,10 +17,11 @@ workflow: stages: - tools - build + - build-testing + - build-release - test - analyze - - integration-test - - build-release + - test-legacy - deploy - .post @@ -25,8 +31,9 @@ include: - local: "/.gitlab/ci/.code-quality-ci.yml" - local: "/.gitlab/ci/.security-and-compliance-ci.yml" - local: "/.gitlab/ci/.test.yml" - - local: "/.gitlab/ci/.integration-test-containerlab.yml" - - local: "/.gitlab/ci/.integration-test.yml" - local: "/.gitlab/ci/.uml-autogen-ci.yml" - local: "/.gitlab/ci/.renovate.yml" - local: "/.gitlab/ci/.mk-docs-deploy.yml" + - local: "/.gitlab/ci/legacy/.test.yml" + #- local: "/.gitlab/ci/legacy/.integration-test-containerlab.yml" + #- local: "/.gitlab/ci/legacy/.integration-test.yml" diff --git a/.gitlab/ci/.build-container-images.yml b/.gitlab/ci/.build-container-images.yml index ea3ee5a32..512dce387 100644 --- a/.gitlab/ci/.build-container-images.yml +++ b/.gitlab/ci/.build-container-images.yml @@ -1,53 +1,76 @@ .build: &build stage: build - tags: - - shell-builder + image: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/docker:latest + services: + - name: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/docker:latest + alias: docker variables: - TAG: $CI_COMMIT_SHA + DOCKER_TLS_CERTDIR: "/certs" + before_script: + - apk add git + - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY + - docker login -u $CI_DEPENDENCY_PROXY_USER -p $CI_DEPENDENCY_PROXY_PASSWORD $CI_DEPENDENCY_PROXY_SERVER needs: [] -build-controller-testing-image: - script: - - docker buildx build -t "$GOSDN_TESTING_IMAGE" -f "${CI_PROJECT_DIR}/controller/controller.Dockerfile" --target "builder" --build-arg "GOLANG_VERSION=$GOLANG_VERSION" --build-arg "BUILDARGS=$BUILDARGS" --build-arg "GITLAB_PROXY=${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/" . - - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY - - docker push "$GOSDN_TESTING_IMAGE" - <<: *build + +.build-testing: &build-testing + stage: build-testing + image: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/docker:latest + services: + - name: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/docker:latest + alias: docker + variables: + DOCKER_TLS_CERTDIR: "/certs" + before_script: + - apk add git + - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY + - docker login -u $CI_DEPENDENCY_PROXY_USER -p $CI_DEPENDENCY_PROXY_PASSWORD $CI_DEPENDENCY_PROXY_SERVER build-controller-image: script: - - docker buildx build -t "$CI_REGISTRY_IMAGE:$TAG" -f "${CI_PROJECT_DIR}/controller/controller.Dockerfile" --build-arg "GOLANG_VERSION=$GOLANG_VERSION" --build-arg "BUILDARGS=$BUILDARGS" --build-arg "GITLAB_PROXY=${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/" . - - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY - - docker push "$CI_REGISTRY_IMAGE:$TAG" + - docker buildx build -t "$CI_REGISTRY_IMAGE:$DOCKER_TAG" -f "${CI_PROJECT_DIR}/controller/controller.Dockerfile" --build-arg "GOLANG_VERSION=$GOLANG_VERSION" --build-arg "BUILDARGS=$BUILDARGS" --build-arg "GITLAB_PROXY=${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/" . + - docker push "$CI_REGISTRY_IMAGE:$DOCKER_TAG" <<: *build build-cli-image: script: - CLI_IMAGE_NAME="${CI_REGISTRY_IMAGE}/gosdnc" - - docker buildx build -t "$CLI_IMAGE_NAME:$TAG" -f "${CI_PROJECT_DIR}/cli/cli.Dockerfile" --build-arg "GOLANG_VERSION=$GOLANG_VERSION" --build-arg "BUILDARGS=$BUILDARGS" --build-arg "GITLAB_PROXY=${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/" . - - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY - - docker push "$CLI_IMAGE_NAME:$TAG" + - docker buildx build -t "$CLI_IMAGE_NAME:$DOCKER_TAG" -f "${CI_PROJECT_DIR}/cli/cli.Dockerfile" --build-arg "GOLANG_VERSION=$GOLANG_VERSION" --build-arg "BUILDARGS=$BUILDARGS" --build-arg "GITLAB_PROXY=${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/" . + - docker push "$CLI_IMAGE_NAME:$DOCKER_TAG" <<: *build build-venv-manager-image: script: - VENV_MANAGER_IMAGE_NAME="${CI_REGISTRY_IMAGE}/venv-manager" - - docker buildx build -t "$VENV_MANAGER_IMAGE_NAME:$TAG" -f "${CI_PROJECT_DIR}/applications/venv-manager/venv-manager.Dockerfile" --build-arg "GOLANG_VERSION=$GOLANG_VERSION" --build-arg "GITLAB_PROXY=${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/" . - - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY - - docker push "$VENV_MANAGER_IMAGE_NAME:$TAG" + - docker buildx build -t "$VENV_MANAGER_IMAGE_NAME:$DOCKER_TAG" -f "${CI_PROJECT_DIR}/applications/venv-manager/venv-manager.Dockerfile" --build-arg "GOLANG_VERSION=$GOLANG_VERSION" --build-arg "GITLAB_PROXY=${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/" . + - docker push "$VENV_MANAGER_IMAGE_NAME:$DOCKER_TAG" <<: *build build-arista-routing-engine-image: script: - ARISTA_ROUTING_ENGINE_IMAGE_NAME="${CI_REGISTRY_IMAGE}/arista-routing-engine" - - docker buildx build -t "$ARISTA_ROUTING_ENGINE_IMAGE_NAME:$TAG" -f "${CI_PROJECT_DIR}/applications/arista-routing-engine/arista-routing-engine.Dockerfile" --build-arg "GOLANG_VERSION=$GOLANG_VERSION" --build-arg "GITLAB_PROXY=${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/" . - - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY - - docker push "$ARISTA_ROUTING_ENGINE_IMAGE_NAME:$TAG" + - docker buildx build -t "$ARISTA_ROUTING_ENGINE_IMAGE_NAME:$DOCKER_TAG" -f "${CI_PROJECT_DIR}/applications/arista-routing-engine/arista-routing-engine.Dockerfile" --build-arg "GOLANG_VERSION=$GOLANG_VERSION" --build-arg "GITLAB_PROXY=${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/" . + - docker push "$ARISTA_ROUTING_ENGINE_IMAGE_NAME:$DOCKER_TAG" <<: *build build-plugin-registry-image: script: - PLUGIN_REGISTRY_IMAGE_NAME="${CI_REGISTRY_IMAGE}/plugin-registry" - - docker buildx build -t "$PLUGIN_REGISTRY_IMAGE_NAME:$TAG" -f "${CI_PROJECT_DIR}/plugin-registry/plugin-registry.Dockerfile" --build-arg "GOLANG_VERSION=$GOLANG_VERSION" --build-arg "GITLAB_PROXY=${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/" . - - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY - - docker push "$PLUGIN_REGISTRY_IMAGE_NAME:$TAG" + - docker buildx build -t "$PLUGIN_REGISTRY_IMAGE_NAME:$DOCKER_TAG" -f "${CI_PROJECT_DIR}/plugin-registry/plugin-registry.Dockerfile" --build-arg "GOLANG_VERSION=$GOLANG_VERSION" --build-arg "GITLAB_PROXY=${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/" . + - docker push "$PLUGIN_REGISTRY_IMAGE_NAME:$DOCKER_TAG" <<: *build + +build-integration-test-images: + needs: ["build-controller-image"] + script: + # Build certs + - apk add openssl make + - make generate-certs + # Build gosdn with ssl certificates + - docker buildx build -t "$CI_REGISTRY_IMAGE:${DOCKER_TAG}_integration-test" -f "${CI_PROJECT_DIR}/.gitlab/ci/gosdn-integration.Dockerfile" --build-arg "GOSDN_IMAGE=$CI_REGISTRY_IMAGE:${DOCKER_TAG}" . + # Update gnmi-target with ssl certificates + - docker buildx build -t $GNMI_TARGET_INTEGRATION_IMAGE -f "${CI_PROJECT_DIR}/.gitlab/ci/gnmi-cert-integration.Dockerfile" --build-arg "GNMI_TARGET_IMAGE=${GNMI_TARGET_IMAGE}" . + # Push images + - docker push "$CI_REGISTRY_IMAGE:${DOCKER_TAG}_integration-test" + - docker push $GNMI_TARGET_INTEGRATION_IMAGE + <<: *build-testing diff --git a/.gitlab/ci/.code-quality-ci.yml b/.gitlab/ci/.code-quality-ci.yml index 85db5c48d..ecfcef2cd 100644 --- a/.gitlab/ci/.code-quality-ci.yml +++ b/.gitlab/ci/.code-quality-ci.yml @@ -1,7 +1,7 @@ variables: GOLANG_VERSION: "1.21" code-quality: - image: golangci/golangci-lint:v1.55.2-alpine + image: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/golangci/golangci-lint:v1.55.2-alpine stage: analyze script: # writes golangci-lint output to gl-code-quality-report.json diff --git a/.gitlab/ci/.integration-test.yml b/.gitlab/ci/.integration-test.yml deleted file mode 100644 index 2825458dd..000000000 --- a/.gitlab/ci/.integration-test.yml +++ /dev/null @@ -1,33 +0,0 @@ -.integration-test: &integration-test - image: $GOSDN_TESTING_IMAGE - stage: integration-test - needs: - ["containerlab-deploy"] - variables: - GOSDN_LOG: "nolog" - GOSDN_TEST_API_ENDPOINT: "10.254.254.105:${GOSDN_GRPC_PORT}" - CEOS_TEST_ENDPOINT: "10.254.254.105:${CEOS1_PORT}" - GOSDN_TEST_USER: "admin" - GOSDN_TEST_PASSWORD: "admin" - - # NOTE: Current test setup and runners are changed, therefore this test is not possible to run at the moment - #integration-test:nucleus: - # <<: *integration-test - # script: - # - ${CI_PROJECT_DIR}/.gitlab/ci/scripts/wait-for-it.sh ${CEOS_TEST_ENDPOINT} -s -t 180 -- echo "CEOS is up" - # - cd controller/ - # - make integration-test-nucleus - -integration-test:api: - <<: *integration-test - variables: - K8S_OP: "getenv" - script: - - cd controller/ - - make integration-test-api - -integration-test:cli: - <<: *integration-test - script: - - cd cli/ - - echo "Your tests here" diff --git a/.gitlab/ci/.test.yml b/.gitlab/ci/.test.yml index 4edcd3c59..9a20eb0c0 100644 --- a/.gitlab/ci/.test.yml +++ b/.gitlab/ci/.test.yml @@ -1,34 +1,39 @@ .test: &test - image: $GOSDN_TESTING_IMAGE stage: test - rules: - - when: on_success - variables: - GOSDN_LOG: "nolog" - GOSDN_CHANGE_TIMEOUT: "5000ms" - coverage: '/total:\s+\(statements\)\s+(\d+.\d+\%)/' - artifacts: - when: always - reports: - junit: report.xml - coverage_report: - coverage_format: cobertura - path: ./controller/coverage.xml - needs: - - build-controller-testing-image -unit-test: - script: - - cd controller - - make ci-unit-test - after_script: - - cd controller - - go tool cover -func=coverage.out - - gocover-cobertura < coverage.out > coverage.xml - <<: *test - -controller-test: +integration-test-controller: + image: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/golang:$GOLANG_VERSION-bookworm + needs: + - ["build-integration-test-images"] + #image: debian:latest + variables: + MONGO_INITDB_ROOT_USERNAME: root + MONGO_INITDB_ROOT_PASSWORD: example + FF_NETWORK_PER_BUILD: 1 + services: + - name: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/mongo:5 + alias: mongo + - name: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/rabbitmq:3-management + alias: rabbitmq + variables: + HEALTHCHECK_TCP_PORT: "5672" + - name: $PLUGIN_REGISTRY_IMAGE_NAME:$DOCKER_TAG + - name: $GNMI_TARGET_INTEGRATION_IMAGE + alias: gnmi-target_1 + command: ["start", "--cert", "/etc/gnmi-target/ssl/certs/gnmi-target-selfsigned.crt", "--key", "/etc/gnmi-target/ssl/private/gnmi-target-selfsigned.key", "--ca_file", "/etc/gnmi-target/ssl/ca.crt"] + - name: $GNMI_TARGET_INTEGRATION_IMAGE + alias: gnmi-target_2 + command: ["start", "--cert", "/etc/gnmi-target/ssl/certs/gnmi-target-selfsigned.crt", "--key", "/etc/gnmi-target/ssl/private/gnmi-target-selfsigned.key", "--ca_file", "/etc/gnmi-target/ssl/ca.crt"] + # Use gosdn docker image from this branch + # Uncomment later when fixed. See: https://code.fbi.h-da.de/danet/gosdn/-/issues/335 + #- name: "$CI_REGISTRY_IMAGE:${DOCKER_TAG}_integration-test" + # alias: gosdn + # variables: + # GOSDN_ADMIN_PASSWORD: TestPassword + # command: ["--config", "/app/configs/integration-test-gosdn.toml", "--security", "insecure"] script: - - cd controller - - make ci-controller-test + # Remove later when fixed. See: https://code.fbi.h-da.de/danet/gosdn/-/issues/335 + - make build-gosdn + - cd artifacts && GOSDN_ADMIN_PASSWORD=TestPassword ./gosdn --config ../controller/configs/integration-test-gosdn.toml --security insecure & + - INTEGRATION_TEST_CONTROLLER_URL="localhost:55055" go test ./integration-tests/* <<: *test diff --git a/.gitlab/ci/gnmi-cert-integration.Dockerfile b/.gitlab/ci/gnmi-cert-integration.Dockerfile new file mode 100644 index 000000000..1aa3d0c16 --- /dev/null +++ b/.gitlab/ci/gnmi-cert-integration.Dockerfile @@ -0,0 +1,8 @@ +ARG GNMI_TARGET_IMAGE=registry.code.fbi.h-da.de/danet/gnmi-target/debian:latest + +FROM ${GNMI_TARGET_IMAGE} + +RUN mkdir -p /etc/gnmi-target/ssl/certs/ +RUN mkdir -p /etc/gnmi-target/ssl/private/ + +COPY ./artifacts/ssl/gnmi-target /etc/gnmi-target/ssl diff --git a/.gitlab/ci/gosdn-integration.Dockerfile b/.gitlab/ci/gosdn-integration.Dockerfile new file mode 100644 index 000000000..7629a5218 --- /dev/null +++ b/.gitlab/ci/gosdn-integration.Dockerfile @@ -0,0 +1,10 @@ +ARG GOSDN_IMAGE + +FROM ${GOSDN_IMAGE} + +RUN mkdir /app/ssl +COPY ./artifacts/ssl/gosdn /app/ssl + +#COPY .gitlab/ci/test-start.sh test-start.sh +#RUN chmod +x test-start.sh +#ENTRYPOINT ["./test-start.sh"] diff --git a/.gitlab/ci/.integration-test-containerlab.yml b/.gitlab/ci/legacy/.integration-test-containerlab.yml similarity index 92% rename from .gitlab/ci/.integration-test-containerlab.yml rename to .gitlab/ci/legacy/.integration-test-containerlab.yml index 467fce876..4cbc4d9a1 100644 --- a/.gitlab/ci/.integration-test-containerlab.yml +++ b/.gitlab/ci/legacy/.integration-test-containerlab.yml @@ -3,8 +3,8 @@ variables: CLAB_DIR: "/home/gitlab-runner/clab" CLAB_NAME: "clab${CI_PIPELINE_IID}" -containerlab-deploy: - stage: integration-test +legacy-containerlab-deploy: + stage: test-legacy tags: - shell-containerlab needs: ["build-controller-image", "build-controller-testing-image"] @@ -38,16 +38,15 @@ containerlab-deploy: dotenv: ${CI_PROJECT_DIR}/build.env -containerlab-destroy: - stage: integration-test +legacy-containerlab-destroy: + stage: test-legacy tags: - shell-containerlab needs: [ - "containerlab-deploy", - #"integration-test:nucleus", - "integration-test:api" - + "legacy-containerlab-deploy", + "legacy-integration-test-legacy:nucleus", + "legacy-integration-test-legacy:api" ] before_script: - cd ${CLAB_DIR} diff --git a/.gitlab/ci/legacy/.integration-test.yml b/.gitlab/ci/legacy/.integration-test.yml new file mode 100644 index 000000000..c999735bc --- /dev/null +++ b/.gitlab/ci/legacy/.integration-test.yml @@ -0,0 +1,32 @@ +.legacy-integration-test: &legacy-integration-test + image: $GOSDN_TESTING_IMAGE + stage: test-legacy + needs: + ["legacy-containerlab-deploy"] + variables: + GOSDN_LOG: "nolog" + GOSDN_TEST_API_ENDPOINT: "10.254.254.105:${GOSDN_GRPC_PORT}" + CEOS_TEST_ENDPOINT: "10.254.254.105:${CEOS1_PORT}" + GOSDN_TEST_USER: "admin" + GOSDN_TEST_PASSWORD: "admin" + +legacy-integration-test-legacy:nucleus: + <<: *legacy-integration-test + script: + - ${CI_PROJECT_DIR}/.gitlab/ci/scripts/wait-for-it.sh ${CEOS_TEST_ENDPOINT} -s -t 180 -- echo "CEOS is up" + - cd controller/ + - make integration-test-nucleus + +legacy-integration-test-legacy:api: + <<: *legacy-integration-test + variables: + K8S_OP: "getenv" + script: + - cd controller/ + - make integration-test-api + +legacy-integration-test:cli: + <<: *legacy-integration-test + script: + - cd cli/ + - echo "Your tests here" diff --git a/.gitlab/ci/legacy/.test.yml b/.gitlab/ci/legacy/.test.yml new file mode 100644 index 000000000..bc17769e6 --- /dev/null +++ b/.gitlab/ci/legacy/.test.yml @@ -0,0 +1,33 @@ +.legacy-test: &legacy-test + image: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/golang:$GOLANG_VERSION-bookworm + stage: test-legacy + rules: + - when: on_success + variables: + GOSDN_LOG: "nolog" + GOSDN_CHANGE_TIMEOUT: "5000ms" + coverage: '/total:\s+\(statements\)\s+(\d+.\d+\%)/' + artifacts: + when: always + reports: + junit: report.xml + coverage_report: + coverage_format: cobertura + path: ./controller/coverage.xml + needs: [] + +legacy-unit-test: + script: + - cd controller + - make ci-unit-test + after_script: + - cd controller + - go tool cover -func=coverage.out + - gocover-cobertura < coverage.out > coverage.xml + <<: *legacy-test + +#legacy-controller-test: +# script: +# - cd controller +# - make ci-controller-test +# <<: *legacy-test diff --git a/Makefile b/Makefile index 0605bfb10..d81179029 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ MAKEFILE_SUBDIR := ./makefiles GOCMD=go GOBUILD=$(GOCMD) build -GOCLEAN=$(GOCMD) clean +GOCLEAN=$(GOCMD) clean -cache -fuzzcache -testcache -modcache BUILD_ARTIFACTS_PATH=artifacts PLUGIN_NAME= bundled_plugin.zip @@ -73,20 +73,34 @@ shell-orchestrator: start: build-gosdn ./$(BUILD_ARTIFACTS_PATH)/gosdn -l debug --config ./controller/configs/gosdn.toml -start-virt-manager-example: build containerize-plugin-registry +virt-manager-example-start: build containerize-plugin-registry ./scripts/manage_virt_env.sh --mode start --topology dev_env_data/clab/basic_two_aristas.yaml --sdnconfig dev_env_data/sdn/basic_two_aristas.json -stop-virt-manager-example: +virt-manager-example-stop: ./scripts/manage_virt_env.sh --mode stop --topology dev_env_data/clab/basic_two_aristas.yaml -start-dev-env: containerize-gosdn containerize-plugin-registry - ./scripts/simple-dev-setup.sh --mode start --topology dev_env_data/clab/basic_two_aristas.yaml +dev-env-start: containerize-gosdn containerize-plugin-registry + ./scripts/simple-dev-setup.sh --mode start --topology dev_env_data/clab/basic_two_gnmi_targets.yaml -stop-dev-env: - ./scripts/simple-dev-setup.sh --mode stop --topology dev_env_data/clab/basic_two_aristas.yaml +dev-env-stop: + ./scripts/simple-dev-setup.sh --mode stop --topology dev_env_data/clab/basic_two_gnmi_targets.yaml generate-certs: generate-gnmi-target-certs generate-gosdn-certs +controller-integration-tests: generate-certs containerize-gosdn containerize-plugin-registry + docker-compose -f dev_env_data/docker-compose/integration-test_docker-compose.yml down + docker-compose -f dev_env_data/docker-compose/integration-test_docker-compose.yml up -d + go test ./integration-tests/* + docker-compose -f dev_env_data/docker-compose/integration-test_docker-compose.yml down + +controller-integration-tests-debug-up: generate-certs containerize-gosdn containerize-plugin-registry + docker-compose -f dev_env_data/docker-compose/integration-test_docker-compose.yml up -d + +controller-integration-tests-debug-down: + docker-compose -f dev_env_data/docker-compose/integration-test_docker-compose.yml down + +# Warning: Depending on you go configuration might also clean caches, modules and docker containers from your other projects. clean: $(GOCLEAN) - rm -rf $(BUILD_ARTIFACTS_PATH) + rm -rf $(BUILD_ARTIFACTS_PATH) $(TOOLS_DIR) + docker system prune -af diff --git a/README.md b/README.md index 9afdfb484..f560b2c23 100644 --- a/README.md +++ b/README.md @@ -34,10 +34,10 @@ There you can also find some tutorials to get to know the SDN controller: - [Additional services](#additional-services) - [Configuration file](#configuration-file) - [Development-Tutorial](#development-tutorial) +- [Integration tests](#integration-tests) - [Contributing](CONTRIBUTING.md) - [License](LICENSE) - [CI Status](#ci-status) -- [Development Tutorial](#development-tutorial) --- @@ -56,7 +56,7 @@ network using one unified controller. ## Example -A simple showcase how the controller can be adressed after +A simple showcase how the controller can be addressed after `make containerlab-start` is shown below:  @@ -68,7 +68,7 @@ A simple showcase how the controller can be adressed after - The `cli` is the CLI to manage the `controller`. - `csbi` is the implementation of Containerised-Southbound-Interfaces (based on the idea and the proof of concept of Manuel Kieweg). Allowing to request - capabilities of MNEs and generate a containerised Southbound-Interface based + capabilities of MNEs and generate a containerized Southbound-Interface based on them. They are currently unsupported. - `controller` represents the `goSDN-controller`. @@ -96,7 +96,7 @@ Any network element directly configured by `goSDN` ## Launch goSDN Controller local In this chapter, you learn how to launch the goSDN controller. -Firstly, make sure that you're located in the root directory of gosdn. +Firstly, make sure that you're located in the root directory of goSDN. `goSDN` provides a `Makefile` for all common use cases. ```sh @@ -125,7 +125,7 @@ running `./gosdn` from the shell: ## Getting Started -If you want to use the the [playground](#playground) you have to make sure you +If you want to use the [playground](#playground) you have to make sure you have [containerlab](https://containerlab.dev/install/) installed on your system. @@ -201,9 +201,9 @@ For the storage system: For the event system (RabbitMQ broker): - `amqpprefix`: the URI prefix that is needed to connect to the RabbitMQ broker. -- `amqphost`: ip adress of the broker +- `amqphost`: IP address of the broker - `amqpport`: port of the broker -- `amqpuser`: user name of credentials to access the broker, default value is `guest` +- `amqpuser`: username of credentials to access the broker, default value is `guest` - `amqppassword`: user password of credentials to access the broker, default is `guest` For the plugin registry: @@ -300,3 +300,13 @@ To develop applications, we provide a framework that can be found [here](https:/ The framework provides some basic code to easily set up the subscription to the event system of the controller, so that your application can get notified via the events published by the RabbitMQ server about information you would like to receive. This includes functions to register and subscribe to the used server. The information you receive includes changes on network elements like if a value of a YANG path changes or other changes like additions or deletions of entities. Examples where the application framework is used can be found [here](https://code.fbi.h-da.de/danet/gosdn/-/tree/master/applications). + +## Integration tests + +The integration tests are currently in its own folder named `integration-tests`, as they use a complete black box design. +The idea is to test as many of our code with as little tests as possible to get a "catch all" approach where a test may fail and hint for a problem, without really telling us what the problem is. +As of the nature of this project many people contribute only a small part and often don't have time to write good unit-tests. +Therefore, we simply want to make sure that a change doesn't break anything important. + +There exists a `example_tests` folder where examples of using the `integrationTestUtils` are shown. Each test should use the appropriate set-up and tear-down/clean-up functions, so that each test operates independent of each other. + diff --git a/applications/arista-routing-engine/arista-routing-engine.Dockerfile b/applications/arista-routing-engine/arista-routing-engine.Dockerfile index 62e45a37c..6df44a04b 100644 --- a/applications/arista-routing-engine/arista-routing-engine.Dockerfile +++ b/applications/arista-routing-engine/arista-routing-engine.Dockerfile @@ -1,6 +1,6 @@ ARG GOLANG_VERSION=1.21 ARG BUILDARGS -ARG $GITLAB_PROXY +ARG GITLAB_PROXY FROM ${GITLAB_PROXY}golang:$GOLANG_VERSION-alpine as builder WORKDIR /gosdn/ diff --git a/applications/venv-manager/venv-manager.Dockerfile b/applications/venv-manager/venv-manager.Dockerfile index a4f8cb9b0..4eece74d6 100644 --- a/applications/venv-manager/venv-manager.Dockerfile +++ b/applications/venv-manager/venv-manager.Dockerfile @@ -1,6 +1,6 @@ ARG GOLANG_VERSION=1.21 ARG BUILDARGS -ARG $GITLAB_PROXY=code.fbi.h-da.de:443/danet/dependency_proxy/containers +ARG GITLAB_PROXY=code.fbi.h-da.de:443/danet/dependency_proxy/containers FROM ${GITLAB_PROXY}golang:$GOLANG_VERSION-bookworm AS builder diff --git a/applications/venv-manager/venv-manager/venv-manager.go b/applications/venv-manager/venv-manager/venv-manager.go index ddb0df5f2..15de1ede0 100644 --- a/applications/venv-manager/venv-manager/venv-manager.go +++ b/applications/venv-manager/venv-manager/venv-manager.go @@ -137,7 +137,7 @@ func (v *VenvManager) CreateSDNConfigFile() error { return nil } -// getSDNConfigData gets the sDN configuration data. +// getSDNConfigData gets the SDN configuration data. func (v *VenvManager) getSDNConfigData() (*string, error) { conn, err := v.createConnection() if err != nil { diff --git a/applications/ws-events/ws-events.Dockerfile b/applications/ws-events/ws-events.Dockerfile index 442629743..04223f4a4 100644 --- a/applications/ws-events/ws-events.Dockerfile +++ b/applications/ws-events/ws-events.Dockerfile @@ -1,6 +1,6 @@ ARG GOLANG_VERSION=1.21 ARG BUILDARGS -ARG $GITLAB_PROXY +ARG GITLAB_PROXY FROM ${GITLAB_PROXY}golang:$GOLANG_VERSION-alpine as builder WORKDIR /app/ diff --git a/controller/Makefile b/controller/Makefile index d558d5c61..14fb43fef 100644 --- a/controller/Makefile +++ b/controller/Makefile @@ -9,7 +9,7 @@ GOBUILD=$(GOCMD) build GOCLEAN=$(GOCMD) clean BINARY_NAME=gosdn -# Tool Vesions +# Tool Versions GOTESTSUM_VERSION=v1.8.1 MOCKERY_VERSION=v2.20.0 GOCOVER_COBERTURA=v1.2.0 @@ -43,27 +43,11 @@ start-insecure: clean build unit-test: install-tools ENVIRONMENT=testing ./$(TOOLS_DIR)/gotestsum --junitfile report.xml --format testname -- -short -race $$( go list ./... | grep -v /forks/ | grep -v /mocks ) -v -trimpath -coverprofile=coverage.out -controller-test: install-tools - ENVIRONMENT=testing ./$(TOOLS_DIR)/gotestsum --junitfile report.xml --format testname -- -race -v -run TestRun +show-unit-test-coverage: unit-test + go tool cover -html=coverage.out ci-unit-test: ci-install-tools ENVIRONMENT=testing gotestsum --junitfile report.xml --format testname -- -short -race $$( go list ./... | grep -v /forks/ | grep -v /mocks ) -v -trimpath -coverprofile=coverage.out -covermode atomic -timeout 30m -ci-controller-test: ci-install-tools - ENVIRONMENT=testing gotestsum --junitfile report.xml --format testname -- -race -v -run TestRun -trimpath -coverprofile=coverage.out - -integration-test-nucleus: - ENVIRONMENT=testing &&\ - cd ./test/integration &&\ - go test -race -v -run TestGnmi_SetIntegration &&\ - go test -race -v -run TestGnmi_GetIntegration &&\ - go test -race -v -run TestGnmi_SubscribeIntegration &&\ - go test -race -v -run TestGnmi_CapabilitiesIntegration - -integration-test-api: - ENVIRONMENT=testing &&\ - cd ./api &&\ - go test -race -v -run TestApiIntegration - generate-mocks: install-tools ./$(TOOLS_DIR)/mockery --all --dir "./interfaces/" diff --git a/controller/api/apiIntegration_test.go b/controller/api/apiIntegration_test.go deleted file mode 100644 index 99e5d4b62..000000000 --- a/controller/api/apiIntegration_test.go +++ /dev/null @@ -1,146 +0,0 @@ -package api - -import ( - "context" - "errors" - "testing" - - mnepb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/networkelement" - tpb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/transport" - "github.com/google/uuid" - guuid "github.com/google/uuid" - "github.com/openconfig/gnmi/proto/gnmi" - "github.com/openconfig/ygot/ygot" - "github.com/spf13/viper" -) - -// This functions complexity is too high, but this will be addresses once the -// TestSetup is refactored. -// -//nolint:gocyclo -func TestApiIntegration(t *testing.T) { - // TDOO: Remove once openshift grpc support is available - t.Skip("skipped due to openshift limitations") - if testing.Short() { - t.Skip("skipping integration test") - } - - path, err := ygot.StringToStructuredPath(testPath) - if err != nil { - t.Error(err) - } - - tests := []struct { - name string - wantErr bool - }{ - { - name: "default", - wantErr: false, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - defer viper.Reset() - if err := Init(context.TODO(), testAPIEndpoint); (err != nil) != tt.wantErr { - if errors.As(err, &viper.ConfigFileNotFoundError{}) { - t.Errorf("gosdn cli init error = %v, wantErr %v", err, tt.wantErr) - return - } - } - cliPnd := viper.GetString("CLI_PND") - cliSbi := viper.GetString("CLI_SBI") - - suid, err := uuid.Parse(cliSbi) - if err != nil { - t.Error(err) - } - puid, err := uuid.Parse(cliPnd) - if err != nil { - t.Error(err) - } - - opt := &tpb.TransportOption{ - Address: testAddress, - Username: testUsername, - Password: testPassword, - TransportOption: &tpb.TransportOption_GnmiTransportOption{ - GnmiTransportOption: &tpb.GnmiTransportOption{}, - }, - } - if _, err := AddNetworkElement( - context.TODO(), - testAPIEndpoint, - "test-networkElement", - opt, - suid, - puid, - []string{}, - ); (err != nil) != tt.wantErr { - t.Errorf("gosdn cli add-networkElement error = %v, wantErr %v", err, tt.wantErr) - return - } - mneid := viper.GetString("LAST_NETWORK_ELEMENT_UUID") - - _, err = GetNetworkElement( - context.TODO(), - testAPIEndpoint, - cliPnd, - mneid, - ) - if (err != nil) != tt.wantErr { - t.Errorf("gosdn cli request error = %v, wantErr %v", err, tt.wantErr) - return - } - - _, err = GetNetworkElement( - context.TODO(), - testAPIEndpoint, - cliPnd, - mneid, - ) - if (err != nil) != tt.wantErr { - t.Errorf("gosdn cli get-networkElement error = %v, wantErr %v", err, tt.wantErr) - return - } - - hostname := guuid.New().String() - hostnameAsTypedValue := &gnmi.TypedValue{ - Value: &gnmi.TypedValue_StringVal{ - StringVal: hostname, - }, - } - _, err = ChangeRequest( - context.TODO(), - testAPIEndpoint, - mneid, - cliPnd, - path, - hostnameAsTypedValue, - mnepb.ApiOperation_API_OPERATION_UPDATE, - ) - if (err != nil) != tt.wantErr { - t.Errorf("gosdn cli set error = %v, wantErr %v", err, tt.wantErr) - return - } - - resp, err := GetNetworkElement(context.TODO(), testAddress, testUsername, testPassword) - if err != nil { - if !tt.wantErr { - t.Errorf("Get() error = %v, wantErr %v", err, tt.wantErr) - } - return - } - var got string - if resp != nil { - got = resp.Mne.Name - } else { - t.Errorf("integration test failed got cannot be nil") - } - if got != hostname { - t.Errorf("integration test failed = got: %v, want: %v", got, hostname) - } - }) - } -} diff --git a/controller/api/initialise_test.go b/controller/api/initialise_test.go index 4fa24cb91..c05da0204 100644 --- a/controller/api/initialise_test.go +++ b/controller/api/initialise_test.go @@ -257,8 +257,6 @@ func bufDialer(context.Context, string) (net.Conn, error) { return lis.Dial() } -const testPath = "/system/config/hostname" - var testAddress = "10.254.254.105:6030" var testAPIEndpoint = "gosdn-latest.apps.ocp.fbi.h-da.de" var testUsername = "admin" diff --git a/controller/cmd/root.go b/controller/cmd/root.go index e3c8ee91f..2fc51cfa2 100644 --- a/controller/cmd/root.go +++ b/controller/cmd/root.go @@ -149,7 +149,7 @@ func initConfig() { log.WithFields(viper.AllSettings()).Debug("current viper config") } -func ensureFileSystemStoreExists(pathToFile string) error { +func ensureFileSystemPathExists(pathToFile string) error { emptyString := []byte("") // create folder if it does not exist if err := os.MkdirAll(configHome, 0777); err != nil { @@ -172,7 +172,7 @@ func ensureViperConfigFileExists() { configPath := filepath.Join(configHome, configName+"."+configType) if _, err := os.Stat(configPath); os.IsNotExist(err) { - err := ensureFileSystemStoreExists(configPath) + err := ensureFileSystemPathExists(configPath) if err != nil { panic(err) } diff --git a/controller/configs/integration-test-gosdn.toml b/controller/configs/integration-test-gosdn.toml new file mode 100644 index 000000000..2708de32e --- /dev/null +++ b/controller/configs/integration-test-gosdn.toml @@ -0,0 +1,21 @@ +amqphost = 'rabbitmq' +amqppassword = 'guest' +amqpport = '5672' +amqpprefix = 'amqp://' +amqpuser = 'guest' +basepnduuid = '5f20f34b-cbd0-4511-9ddc-c50cf6a3b49d' +config = './gosdn/controller/configs/integration-test-gosdn.toml' +csbi-orchestrator = 'localhost:55056' +databaseconnection = 'mongodb://root:example@mongo:27017' +defaultjwtduration = 24 +filesystempathtostores = 'stores' +gnmisubscriptionspath = 'configs/gNMISubscriptions.txt' +help = false +log-level = 'debug' +plugin-folder = 'plugins' +plugin-registry = 'plugin-registry:55057' +security = 'insecure' +socket = ':55055' +tlscacertfile = '/ssl/ca.crt' +tlscertfile = '/ssl/certs/gosdn-selfsigned.crt' +tlskeyfile = '/ssl/private/gosdn-selfsigned.key' diff --git a/controller/controller.Dockerfile b/controller/controller.Dockerfile index 65c04f4e7..56a9bbecc 100644 --- a/controller/controller.Dockerfile +++ b/controller/controller.Dockerfile @@ -1,6 +1,6 @@ ARG GOLANG_VERSION=1.21 ARG BUILDARGS -ARG $GITLAB_PROXY +ARG GITLAB_PROXY FROM ${GITLAB_PROXY}golang:$GOLANG_VERSION-bookworm as builder WORKDIR /gosdn/ @@ -11,8 +11,14 @@ RUN --mount=type=cache,target=/root/go/pkg/mod \ FROM ${GITLAB_PROXY}debian:bookworm-slim WORKDIR /app/ +RUN mkdir -p controller/configs/ && touch controller/configs/gNMISubscriptions.txt + +COPY --from=builder /gosdn/artifacts/gosdn ./gosdn + COPY --from=builder /gosdn/controller/configs/development-gosdn.toml.example ./configs/development-gosdn.toml +COPY --from=builder /gosdn/controller/configs/integration-test-gosdn.toml ./configs/integration-test-gosdn.toml COPY --from=builder /gosdn/controller/configs/containerlab-gosdn.toml.example ./configs/containerlab-gosdn.toml COPY --from=builder /gosdn/controller/configs/gNMISubscriptions.txt.example ./configs/gNMISubscriptions.txt -COPY --from=builder /gosdn/artifacts/gosdn ./gosdn + +EXPOSE 55055 8080 40000 ENTRYPOINT ["./gosdn"] diff --git a/controller/controller.Dockerfile.dockerignore b/controller/controller.Dockerfile.dockerignore index 1fbdb8fde..3b9460bba 100644 --- a/controller/controller.Dockerfile.dockerignore +++ b/controller/controller.Dockerfile.dockerignore @@ -4,8 +4,7 @@ build documentation mocks test -clab-gosdn_csbi_arista_base -clab-gosdn_sts_demo_basic +clab-gosdn* .cobra.yaml .dockerignore .gitlab-ci.yaml @@ -16,3 +15,4 @@ artifacts build-tools models/YangModels models/arista +integration-tests diff --git a/controller/northbound/server/configurationmanagement.go b/controller/northbound/server/configurationmanagement.go index 539a567ac..0dabea7d5 100644 --- a/controller/northbound/server/configurationmanagement.go +++ b/controller/northbound/server/configurationmanagement.go @@ -85,15 +85,14 @@ func (c ConfigurationManagementServer) ExportSDNConfig(ctx context.Context, requ } var sdnConfig = sdnConfig{} + var err error sdnConfig.PndID = request.Pid - networkElements, err := c.mneService.GetAll() + sdnConfig.NetworkElements, err = c.mneService.GetAll() if err != nil { return nil, err } - sdnConfig.NetworkElements = networkElements - sdnConfig.Nodes, err = c.nodeService.GetAll() if err != nil { return nil, err diff --git a/controller/test/integration/nucleusIntegration_test.go b/controller/test/integration/nucleusIntegration_test.go deleted file mode 100644 index 8fdcb85f1..000000000 --- a/controller/test/integration/nucleusIntegration_test.go +++ /dev/null @@ -1,556 +0,0 @@ -package integration - -// import ( -// "context" -// "os" -// "reflect" -// "sort" -// "testing" -// "time" - -// "github.com/google/uuid" - -// mnepb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/networkelement" -// spb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/southbound" -// tpb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/transport" - -// "code.fbi.h-da.de/danet/gosdn/controller/interfaces/change" -// "code.fbi.h-da.de/danet/gosdn/controller/mocks" -// "code.fbi.h-da.de/danet/gosdn/models/generated/openconfig" -// "code.fbi.h-da.de/danet/gosdn/plugins/sdk" - -// "code.fbi.h-da.de/danet/gosdn/controller/customerrs" -// "code.fbi.h-da.de/danet/gosdn/controller/nucleus" -// "code.fbi.h-da.de/danet/gosdn/controller/nucleus/types" -// "code.fbi.h-da.de/danet/gosdn/controller/nucleus/util/proto" -// "code.fbi.h-da.de/danet/gosdn/forks/goarista/gnmi" -// "github.com/google/uuid" -// gpb "github.com/openconfig/gnmi/proto/gnmi" -// log "github.com/sirupsen/logrus" -// pb "google.golang.org/protobuf/proto" -// ) - -// const unreachable = "203.0.113.10:6030" -// const testPath = "/system/config/hostname" - -// var modifiedHostname = "ceos3000" -// var testAddress = "10.254.254.105:6030" -// var testUsername = "admin" -// var testPassword = "arista" -// var opt *tpb.TransportOption -// var gnmiMessages map[string]pb.Message - -// func TestMain(m *testing.M) { -// testSetupIntegration() -// os.Exit(m.Run()) -// } - -// func testSetupIntegration() { -// if os.Getenv("GOSDN_LOG") == "nolog" { -// log.SetLevel(log.PanicLevel) -// } - -// addr := os.Getenv("CEOS_TEST_ENDPOINT") -// if addr != "" { -// testAddress = addr -// log.Infof("CEOS_TEST_ENDPOINT set to %v", testAddress) -// } -// u := os.Getenv("GOSDN_TEST_USER") -// if u != "" { -// testUsername = u -// log.Infof("GOSDN_TEST_USER set to %v", testUsername) -// } -// p := os.Getenv("GOSDN_TEST_PASSWORD") -// if p != "" { -// testPassword = p -// log.Infof("GOSDN_TEST_PASSWORD set to %v", testPassword) -// } - -// gnmiMessages = map[string]pb.Message{ -// "../proto/cap-resp-arista-ceos": &gpb.CapabilityResponse{}, -// "../proto/req-full-node": &gpb.GetRequest{}, -// "../proto/req-full-node-arista-ceos": &gpb.GetRequest{}, -// "../proto/req-interfaces-arista-ceos": &gpb.GetRequest{}, -// "../proto/req-interfaces-interface-arista-ceos": &gpb.GetRequest{}, -// "../proto/req-interfaces-wildcard": &gpb.GetRequest{}, -// "../proto/resp-full-node": &gpb.GetResponse{}, -// "../proto/resp-full-node-arista-ceos": &gpb.GetResponse{}, -// "../proto/resp-interfaces-arista-ceos": &gpb.GetResponse{}, -// "../proto/resp-interfaces-interface-arista-ceos": &gpb.GetResponse{}, -// "../proto/resp-interfaces-wildcard": &gpb.GetResponse{}, -// "../proto/resp-set-system-config-hostname": &gpb.SetResponse{}, -// } -// for k, v := range gnmiMessages { -// if err := proto.Read(k, v); err != nil { -// log.Fatalf("error parsing %v: %v", k, err) -// } -// } - -// opt = &tpb.TransportOption{ -// Address: testAddress, -// Username: testUsername, -// Password: testPassword, -// TransportOption: &tpb.TransportOption_GnmiTransportOption{ -// GnmiTransportOption: &tpb.GnmiTransportOption{}, -// }, -// } -// } - -// func TestGnmi_SetInvalidIntegration(t *testing.T) { -// if testing.Short() { -// t.Skip("skipping integration test") -// } -// type fields struct { -// opt *tpb.TransportOption -// } -// type args struct { -// ctx context.Context -// payload change.Payload -// path string -// } -// tests := []struct { -// name string -// fields fields -// args args -// wantErr bool -// }{ -// { -// name: "destination unreachable", -// fields: fields{ -// opt: &tpb.TransportOption{ -// Address: unreachable, -// TransportOption: &tpb.TransportOption_GnmiTransportOption{ -// GnmiTransportOption: &tpb.GnmiTransportOption{}}, -// }, -// }, -// args: args{ -// ctx: context.Background(), -// payload: change.Payload{}, -// path: "/", -// }, -// wantErr: true, -// }, -// { -// name: "invalid update", -// fields: fields{opt: opt}, -// args: args{ -// ctx: context.Background(), -// payload: change.Payload{}, -// path: "/", -// }, -// wantErr: true, -// }, -// } -// for _, tt := range tests { -// t.Run(tt.name, func(t *testing.T) { -// deviceModel, err := sdk.NewDeviceModel(openconfig.Schema, openconfig.Unmarshal, openconfig.SchemaTreeGzip) -// if err != nil { -// t.Errorf("SetInvalidIntegration() error = %v", err) -// return -// } -// g, err := nucleus.NewTransport(tt.fields.opt, deviceModel) -// if (err != nil) != tt.wantErr { -// t.Errorf("SetInvalidIntegration() error = %v, wantErr %v", err, tt.wantErr) -// return -// } -// err = g.Set(tt.args.ctx, tt.args.payload, tt.args.path, &mocks.Plugin{}) -// if (err != nil) != tt.wantErr { -// t.Errorf("SetInvalidIntegration() error = %v, wantErr %v", err, tt.wantErr) -// return -// } -// }) -// } -// } - -// func TestGnmi_SetValidIntegration(t *testing.T) { -// if testing.Short() { -// t.Skip("skipping integration test") -// } - -// opt := &tpb.TransportOption{ -// Address: testAddress, -// Username: testUsername, -// Password: testPassword, -// TransportOption: &tpb.TransportOption_GnmiTransportOption{ -// GnmiTransportOption: &tpb.GnmiTransportOption{}, -// }, -// } -// pnd, err := nucleus.NewPND("test", "test", uuid.New(), nil, nil, nil, nil) -// if err != nil { -// t.Error(err) -// return -// } -// _, err = pnd.AddNetworkElement("test", opt, nil, uuid.New(), pnd.ID()) -// if err != nil { -// t.Error(err) -// return -// } -// mne, err := pnd.GetNetworkElement("test") -// if err != nil { -// t.Error(err) -// return -// } - -// tests := []struct { -// name string -// apiOp mnepb.ApiOperation -// path string -// value string -// want string -// }{ -// { -// name: "update", -// apiOp: mnepb.ApiOperation_API_OPERATION_UPDATE, -// path: testPath, -// value: modifiedHostname, -// want: modifiedHostname, -// }, -// { -// name: "replace", -// apiOp: mnepb.ApiOperation_API_OPERATION_REPLACE, -// path: "/system/config/domain-name", -// value: modifiedHostname, -// want: modifiedHostname, -// }, -// { -// name: "delete", -// apiOp: mnepb.ApiOperation_API_OPERATION_DELETE, -// path: testPath, -// }, -// } -// for _, tt := range tests { -// tt := tt -// t.Run(tt.name, func(t *testing.T) { -// t.Parallel() - -// n := &server.NetworkElementServer{} - -// cuid, err := n.ChangeMNE(mne.ID(), tt.apiOp, tt.path, tt.value) -// if err != nil { -// t.Error(err) -// return -// } -// if err := n.Commit(cuid); err != nil { -// t.Error(err) -// return -// } -// if err := n.Confirm(cuid); err != nil { -// t.Error(err) -// return -// } -// if tt.name != "delete" { -// resp, err := pnd.Request(mne.ID(), tt.path) -// if err != nil { -// t.Error(err) -// return -// } -// r, ok := resp.(*gpb.GetResponse) -// if !ok { -// t.Error(&customerrs.InvalidTypeAssertionError{ -// Value: resp, -// Type: &gpb.GetResponse{}, -// }) -// return -// } -// got := r.Notification[0].Update[0].Val.GetStringVal() -// if !reflect.DeepEqual(got, tt.want) { -// t.Errorf("GetNetworkElement() got = %v, want %v", got, tt.want) -// } -// } -// }) -// } -// } - -// func TestGnmi_GetIntegration(t *testing.T) { -// if testing.Short() { -// t.Skip("skipping integration test") -// } - -// paths := []string{ -// "/interfaces/interface", -// "system/config/hostname", -// } -// type fields struct { -// opt *tpb.TransportOption -// } -// type args struct { -// ctx context.Context -// params []string -// } -// tests := []struct { -// name string -// fields fields -// args args -// want interface{} -// wantErr bool -// }{ -// { -// name: "default", -// fields: fields{opt: opt}, -// args: args{ -// ctx: context.Background(), -// params: paths[:1], -// }, -// want: gnmiMessages["../proto/resp-interfaces-arista-ceos"], -// wantErr: false, -// }, -// { -// name: "destination unreachable", -// fields: fields{ -// opt: &tpb.TransportOption{ -// Address: unreachable, -// TransportOption: &tpb.TransportOption_GnmiTransportOption{ -// GnmiTransportOption: &tpb.GnmiTransportOption{}}, -// }, -// }, -// args: args{ -// ctx: context.Background(), -// params: paths, -// }, -// want: nil, -// wantErr: true, -// }, -// } -// for _, tt := range tests { -// t.Run(tt.name, func(t *testing.T) { -// deviceModel, err := sdk.NewDeviceModel(openconfig.Schema, openconfig.Unmarshal, openconfig.SchemaTreeGzip) -// if err != nil { -// t.Errorf("Get() error = %v", err) -// return -// } -// g, err := nucleus.NewTransport(tt.fields.opt, deviceModel) -// if err != nil { -// t.Error(err) -// return -// } -// got, err := g.Get(tt.args.ctx, tt.args.params...) -// if (err != nil) != tt.wantErr { -// t.Errorf("Get() error = %v, wantErr %v", err, tt.wantErr) -// return -// } -// if reflect.TypeOf(got) != reflect.TypeOf(tt.want) { -// t.Errorf("Get() got = %v, want %v", got, tt.want) -// } -// }) -// } -// } -// func TestGnmi_SubscribeIntegration(t *testing.T) { -// if testing.Short() { -// t.Skip("skipping integration test") -// } - -// type fields struct { -// opt *tpb.TransportOption -// } -// type args struct { -// ctx context.Context -// opts *gnmi.SubscribeOptions -// } -// tests := []struct { -// name string -// fields fields -// args args -// wantErr bool -// }{ -// { -// name: "default", -// fields: fields{ -// opt: &tpb.TransportOption{ -// Address: testAddress, -// Username: testUsername, -// Password: testPassword, -// Tls: false, -// TransportOption: &tpb.TransportOption_GnmiTransportOption{ -// GnmiTransportOption: &tpb.GnmiTransportOption{ -// Compression: "", -// GrpcDialOptions: nil, -// Token: "", -// Encoding: 0, -// }, -// }, -// }, -// }, -// args: args{ -// ctx: context.Background(), -// opts: &gnmi.SubscribeOptions{ -// Mode: "stream", -// StreamMode: "sample", -// SampleInterval: uint64(1 * time.Second), -// HeartbeatInterval: uint64(100 * time.Millisecond), -// Paths: gnmi.SplitPaths([]string{ -// "/interfaces/interface/name", -// "/system/config/hostname", -// }), -// Target: testAddress, -// }, -// }, -// wantErr: false, -// }, -// { -// name: "wrong path", -// fields: fields{ -// opt: &tpb.TransportOption{ -// TransportOption: &tpb.TransportOption_GnmiTransportOption{ -// GnmiTransportOption: &tpb.GnmiTransportOption{}}, -// }, -// }, -// args: args{ -// opts: &gnmi.SubscribeOptions{ -// Mode: "stream", -// StreamMode: "sample", -// SampleInterval: uint64(1 * time.Second), -// HeartbeatInterval: uint64(100 * time.Millisecond), -// Paths: gnmi.SplitPaths([]string{ -// "interfaces/interface/name", -// "ystem/config/hostname", -// }), -// Target: testAddress, -// }, -// }, -// wantErr: true, -// }, -// { -// name: "destination unreachable", -// fields: fields{ -// opt: &tpb.TransportOption{ -// Address: "203.0.113.10:6030", -// TransportOption: &tpb.TransportOption_GnmiTransportOption{ -// GnmiTransportOption: &tpb.GnmiTransportOption{}}, -// }, -// }, -// args: args{ -// opts: &gnmi.SubscribeOptions{}, -// }, -// wantErr: false, -// }, -// } -// for _, tt := range tests { -// t.Run(tt.name, func(t *testing.T) { -// var wantErr = tt.wantErr -// deviceModel, err := sdk.NewDeviceModel(openconfig.Schema, openconfig.Unmarshal, openconfig.SchemaTreeGzip) -// if err != nil { -// t.Errorf("Subscribe() error = %v", err) -// return -// } -// g, err := nucleus.NewTransport(tt.fields.opt, deviceModel) -// if err != nil { -// t.Error(err) -// return -// } -// ctx := context.WithValue(context.Background(), types.CtxKeyOpts, tt.args.opts) //nolint -// ctx, cancel := context.WithCancel(ctx) -// go func() { -// subErr := g.Subscribe(ctx) -// if (subErr != nil) != wantErr { -// if !wantErr && subErr != nil { -// if subErr.Error() != "rpc error: code = Canceled desc = context canceled" { -// t.Errorf("Subscribe() error = %v, wantErr %v", subErr, tt.wantErr) -// } -// } -// } -// }() -// time.Sleep(time.Second * 3) -// cancel() -// time.Sleep(time.Second * 1) -// }) -// } -// } - -// func TestGnmi_CapabilitiesIntegration(t *testing.T) { -// if testing.Short() { -// t.Skip("skipping integration test") -// } -// type fields struct { -// opt *tpb.TransportOption -// } -// type args struct { -// ctx context.Context -// } -// tests := []struct { -// name string -// fields fields -// args args -// want interface{} -// wantErr bool -// }{ -// { -// name: "supported models", -// fields: fields{opt: opt}, -// args: args{ctx: context.Background()}, -// want: gnmiMessages["../proto/cap-resp-arista-ceos"].(*gpb.CapabilityResponse).SupportedModels, -// wantErr: false, -// }, -// { -// name: "supported encodings", -// fields: fields{opt: opt}, -// args: args{ctx: context.Background()}, -// want: gnmiMessages["../proto/cap-resp-arista-ceos"].(*gpb.CapabilityResponse).SupportedEncodings, -// wantErr: false, -// }, -// { -// name: "gnmi version", -// fields: fields{opt: opt}, -// args: args{ctx: context.Background()}, -// want: gnmiMessages["../proto/cap-resp-arista-ceos"].(*gpb.CapabilityResponse).GNMIVersion, -// wantErr: false, -// }, -// { -// name: "destination unreachable", -// fields: fields{opt: &tpb.TransportOption{ -// Address: "203.0.113.10:6030", -// TransportOption: &tpb.TransportOption_GnmiTransportOption{ -// GnmiTransportOption: &tpb.GnmiTransportOption{}}, -// }, -// }, -// args: args{ctx: context.Background()}, -// want: nil, -// wantErr: true, -// }, -// } -// for _, tt := range tests { -// t.Run(tt.name, func(t *testing.T) { -// deviceModel, err := sdk.NewDeviceModel(openconfig.Schema, openconfig.Unmarshal, openconfig.SchemaTreeGzip) -// if err != nil { -// t.Errorf("Capabilities() error = %v", err) -// return -// } -// tr, err := nucleus.NewTransport(tt.fields.opt, deviceModel) -// if err != nil { -// t.Error(err) -// return -// } -// g, ok := tr.(*nucleus.Gnmi) -// if !ok { -// t.Error(&customerrs.InvalidTypeAssertionError{ -// Value: tr, -// Type: &nucleus.Gnmi{}, -// }) -// } -// resp, err := g.Capabilities(tt.args.ctx) -// if (err != nil) != tt.wantErr { -// t.Errorf("Capabilities() error = %v, wantErr %v", err, tt.wantErr) -// return -// } -// var got interface{} -// switch tt.name { -// case "supported encodings": -// got = resp.(*gpb.CapabilityResponse).SupportedEncodings -// case "supported models": -// t.Skip("test causes false negative") -// got = resp.(*gpb.CapabilityResponse).SupportedModels -// sort.Slice(got.([]*gpb.ModelData), func(i, j int) bool { -// return got.([]*gpb.ModelData)[i].Name < got.([]*gpb.ModelData)[j].Name -// }) -// sort.Slice(tt.want.([]*gpb.ModelData), func(i, j int) bool { -// return tt.want.([]*gpb.ModelData)[i].Name < tt.want.([]*gpb.ModelData)[j].Name -// }) -// case "gnmi version": -// got = resp.(*gpb.CapabilityResponse).GNMIVersion -// default: -// } -// if !reflect.DeepEqual(got, tt.want) { -// t.Errorf("Type() = %v, want %v", got, tt.want) -// } -// }) -// } -// } diff --git a/dev_env_data/clab/basic_two_gnmi_targets.yaml b/dev_env_data/clab/basic_two_gnmi_targets.yaml new file mode 100644 index 000000000..b582864cc --- /dev/null +++ b/dev_env_data/clab/basic_two_gnmi_targets.yaml @@ -0,0 +1,24 @@ +name: gosdn_two_gnmi_targets + +mgmt: + network: gosdn-net + ipv4-subnet: 172.100.0.0/16 + ipv6-subnet: 2001:db8::/64 + +topology: + kinds: + linux: + image: registry.code.fbi.h-da.de/danet/gnmi-target/debian:master + + nodes: + gnmi0: + kind: linux + mgmt-ipv4: 172.100.0.11 + + gnmi1: + kind: linux + mgmt-ipv4: 172.100.0.12 + + links: + - endpoints: ["gnmi0:eth1","gnmi1:eth1"] + - endpoints: ["gnmi0:eth2","gnmi1:eth2"] diff --git a/dev_env_data/clab/demo.clab.yaml b/dev_env_data/clab/demo.clab.yaml index 66a91dfd3..9543d6304 100644 --- a/dev_env_data/clab/demo.clab.yaml +++ b/dev_env_data/clab/demo.clab.yaml @@ -18,7 +18,7 @@ topology: client0: kind: linux - image: registry.code.fbi.h-da.de/danet/gnmi-target/ubuntu:develop + image: registry.code.fbi.h-da.de/danet/gnmi-target/debian:develop binds: - ../../artifacts/ssl:/etc/gnmi-target/ssl cmd: @@ -28,7 +28,7 @@ topology: client1: kind: linux - image: registry.code.fbi.h-da.de/danet/gnmi-target/ubuntu:develop + image: registry.code.fbi.h-da.de/danet/gnmi-target/debian:develop binds: - ../../artifacts/ssl:/etc/gnmi-target/ssl cmd: @@ -38,7 +38,7 @@ topology: client2: kind: linux - image: registry.code.fbi.h-da.de/danet/gnmi-target/ubuntu:develop + image: registry.code.fbi.h-da.de/danet/gnmi-target/debian:develop binds: - ../../artifacts/ssl:/etc/gnmi-target/ssl cmd: diff --git a/dev_env_data/clab/gosdn.clab.yaml b/dev_env_data/clab/gosdn.clab.yaml index 0de625cff..596c9d0c2 100644 --- a/dev_env_data/clab/gosdn.clab.yaml +++ b/dev_env_data/clab/gosdn.clab.yaml @@ -49,7 +49,7 @@ topology: gnmi-target: kind: linux - image: registry.code.fbi.h-da.de/danet/gnmi-target/ubuntu:develop + image: registry.code.fbi.h-da.de/danet/gnmi-target/debian:develop binds: - ../../artifacts/ssl/gnmi-target:/etc/gnmi-target/ssl ports: diff --git a/dev_env_data/docker-compose/integration-test_docker-compose.yml b/dev_env_data/docker-compose/integration-test_docker-compose.yml new file mode 100644 index 000000000..2d2058dad --- /dev/null +++ b/dev_env_data/docker-compose/integration-test_docker-compose.yml @@ -0,0 +1,53 @@ +version: '3' + +# Only use via makefile as otherwise goSDN isn't rebuild! + +services: + mongo: + image: mongo:5 + environment: + MONGO_INITDB_ROOT_USERNAME: root + MONGO_INITDB_ROOT_PASSWORD: example + + rabbitmq: + image: rabbitmq:3-management + healthcheck: + test: rabbitmq-diagnostics -q ping + interval: 30s + timeout: 10s + retries: 5 + + plugin-registry: + image: plugin-registry + + gosdn: + image: gosdn + ports: + - 55055:55055 + - 8080:8080 + - 40000:40000 + depends_on: + gnmi-target: + condition: service_started + mongo: + condition: service_started + plugin-registry: + condition: service_started + rabbitmq: + condition: service_healthy + command: + --config /app/configs/integration-test-gosdn.toml --security insecure + environment: + GOSDN_ADMIN_PASSWORD: TestPassword + volumes: + - ../../artifacts/ssl/gosdn:/app/ssl + + gnmi-target: + image: registry.code.fbi.h-da.de/danet/gnmi-target/debian:master + deploy: + mode: replicated + replicas: 2 + volumes: + - ../../artifacts/ssl/gnmi-target:/etc/gnmi-target/ssl + command: + start --cert /etc/gnmi-target/ssl/certs/gnmi-target-selfsigned.crt --key /etc/gnmi-target/ssl/private/gnmi-target-selfsigned.key --ca_file /etc/gnmi-target/ssl/ca.crt diff --git a/integration-tests/example_tests/controller_test.go b/integration-tests/example_tests/controller_test.go new file mode 100644 index 000000000..14d3833c2 --- /dev/null +++ b/integration-tests/example_tests/controller_test.go @@ -0,0 +1,19 @@ +package integration_test + +import ( + "testing" + + integration_test_utils "code.fbi.h-da.de/danet/gosdn/integration-tests/integrationTestUtils" +) + +func TestExample(t *testing.T) { + conn, err := integration_test_utils.CreateConnection() + if err != nil { + t.Errorf(err.Error()) + } + sndConfig, err := integration_test_utils.PrepareEvironment(conn) + if err != nil { + t.Errorf(err.Error()) + } + defer integration_test_utils.RestoreEnvironment(conn, sndConfig) +} diff --git a/integration-tests/integrationTestUtils/integrationTestUtils.go b/integration-tests/integrationTestUtils/integrationTestUtils.go new file mode 100644 index 000000000..2afa6eb83 --- /dev/null +++ b/integration-tests/integrationTestUtils/integrationTestUtils.go @@ -0,0 +1,72 @@ +package integration_test_utils + +import ( + "context" + "fmt" + "os" + "time" + + configMgmtPb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/configurationmanagement" + ppb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/pnd" + + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" +) + +func CreateConnection() (*grpc.ClientConn, error) { + controller_url := "localhost:55055" + controller_env := os.Getenv("INTEGRATION_TEST_CONTROLLER_URL") + if controller_env != "" { + controller_url = controller_env + } + dialOption := grpc.WithTransportCredentials(insecure.NewCredentials()) + conn, err := grpc.Dial(controller_url, dialOption, grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(100*1024*1024))) + if err != nil { + return nil, err + } + + return conn, nil +} + +func PrepareEvironment(conn *grpc.ClientConn) (string, error) { + ctx := context.Background() + pndService := ppb.NewPndServiceClient(conn) + pndRes, err := pndService.GetPndList(ctx, &ppb.GetPndListRequest{Timestamp: getTimestamp()}) + if err != nil { + return "", err + } + pndID := pndRes.Pnd[0].Id + + configMgmtService := configMgmtPb.NewConfigurationManagementServiceClient(conn) + + sdnConfigResponse, err := configMgmtService.ExportSDNConfig(ctx, &configMgmtPb.ExportSDNConfigRequest{Timestamp: getTimestamp(), Pid: pndID}) + if err != nil { + return "", err + } + + return sdnConfigResponse.SdnConfigData, nil +} + +func RestoreEnvironment(conn *grpc.ClientConn, sdnConfig string) { + ctx := context.Background() + + pndService := ppb.NewPndServiceClient(conn) + pndRes, err := pndService.GetPndList(ctx, &ppb.GetPndListRequest{Timestamp: getTimestamp()}) + if err != nil { + fmt.Println(err) + } + + // currently only support for default PND + pndID := pndRes.Pnd[0].Id + + configMgmtService := configMgmtPb.NewConfigurationManagementServiceClient(conn) + + _, err = configMgmtService.ImportSDNConfig(ctx, &configMgmtPb.ImportSDNConfigRequest{Timestamp: getTimestamp(), Pid: pndID, SdnConfigData: sdnConfig}) + if err != nil { + fmt.Println(err) + } +} + +func getTimestamp() int64 { + return int64(time.Now().Nanosecond()) +} diff --git a/mkdocs.yml b/mkdocs.yml index bb40753ca..16ba4fcad 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -13,7 +13,7 @@ theme: palette: # Palette toggle for light mode - media: "(prefers-color-scheme: light)" - scheme: default + scheme: default primary: white toggle: icon: material/brightness-7 @@ -36,4 +36,4 @@ theme: site_author: goSDN-Team site_description: goSDN is a modern SDN controller based around gnmi, YANG and go repo_name: danet/gosdn -repo_url: https://code.fbi.h-da.de/danet/gosdn \ No newline at end of file +repo_url: https://code.fbi.h-da.de/danet/gosdn diff --git a/plugin-registry/plugin-registry.Dockerfile b/plugin-registry/plugin-registry.Dockerfile index 6448d49d2..a82ea5647 100644 --- a/plugin-registry/plugin-registry.Dockerfile +++ b/plugin-registry/plugin-registry.Dockerfile @@ -1,6 +1,6 @@ ARG GOLANG_VERSION=1.21 ARG BUILDARGS -ARG $GITLAB_PROXY +ARG GITLAB_PROXY FROM ${GITLAB_PROXY}golang:$GOLANG_VERSION-bookworm as builder WORKDIR /plugin-registry/ diff --git a/plugin-registry/plugin-registry.Dockerfile.dockerignore b/plugin-registry/plugin-registry.Dockerfile.dockerignore index d4fbe10ce..ef3ac2462 100644 --- a/plugin-registry/plugin-registry.Dockerfile.dockerignore +++ b/plugin-registry/plugin-registry.Dockerfile.dockerignore @@ -4,8 +4,7 @@ build documentation mocks test -clab-gosdn_csbi_arista_base -clab-gosdn_sts_demo_basic +clab-gosdn* .cobra.yaml .dockeringore .gitlab-ci.yaml -- GitLab