diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 74cbf443ae1520b38978561a2b4f993b6687ebe3..811bc1b83e2070f49862df6758ec3627b27226b1 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 7c93425e6ad49e9ac88a2b1d448291f547099b68..887b52a5d88c91d7051f2f1e1425b66ece674850 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 a6d07de06fb4c0c04521ac7a2443d0a4e2e3b04a..0b61b6ba700ddfe37d69702ad4bcc436f13fbfe6 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,5 +1,4 @@ .git -.gitlab build documentation mocks diff --git a/.gitignore b/.gitignore index ea0772adf6491afa48ac68b273ed753dc8d04444..bdaaaa30d002eadd4186a5dd067f64101162c5ae 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 2ea8eb57a4ebeb8371aecd12d6262e5dc6fb950d..7d116ad582f866b5fd6c1b59281ac43e1b79c953 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 ea3ee5a32695abad454985155e85630f11165339..512dce38737f426f4b65d35799a34745840ec93f 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 85db5c48d28fab4f1c57e97f122d5c3ad4d8cb91..ecfcef2cdbcbadd88f47284617149a3477999152 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 2825458dd5b9b051aec99e2b0d5e621d2c2f3cb2..0000000000000000000000000000000000000000 --- 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 4edcd3c592f6e72403bf3a2a4f8b6ddf6d55d57a..9a20eb0c03c80a40b6a25160ee0dbabd7b7fd1e7 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 0000000000000000000000000000000000000000..1aa3d0c160b4480cf72617eecb93ea120f36bc0d --- /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 0000000000000000000000000000000000000000..7629a5218e9995bd0e35ffb846c96d2d53b785c3 --- /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 467fce8769d0e30e40607914c643358de5b07ca0..4cbc4d9a18a15a0e2f47931267f0717ca19f5261 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 0000000000000000000000000000000000000000..c999735bc1adc2d6062f958ef98e47013c14a202 --- /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 0000000000000000000000000000000000000000..bc17769e6b70bf9caa11273367820eb0da98f16e --- /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 0605bfb103867a566255122ef28e5d25f6ff814a..d811790292c1d3ebaaacd74ee85c3983255f6062 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 9afdfb4845438cf43c3453efcf2f80f4c659031a..f560b2c23b01677661ff82d1bb867ed6f73941df 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 62e45a37ce36098ff4fc6b9894add0e21fc89edd..6df44a04b62256e1b589b559c40f70985e350c4c 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 a4f8cb9b0326b6200aa034c4801408eea551a07d..4eece74d6d3ee33e0f0cc9cb0e71d00e8078f84a 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 ddb0df5f22822dcae530ea492be151807b993032..15de1ede0d4fce6a0a531713ac1bde16df1f84b8 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 44262974369d4283ea8c4fa3c5400bcaa30e2817..04223f4a48dde7aca88a3a792871b90461e19145 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 d558d5c617e0f643a8510cbd1c5b4b99d3a96cc9..14fb43fefe7364094d0a3051d1f6f4af4b12093f 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 99e5d4b62282fb1ae82876235ebd1590505c37d2..0000000000000000000000000000000000000000 --- 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 4fa24cb91bc4e66ed1f3daefaaababddba5ce199..c05da020429b81bd5234296a9897316dc5483e40 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 e3c8ee91fa643ab8636aeb81997ac8eff28449d6..2fc51cfa2d3bfd89f6a58213a60bf7263772e6d5 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 0000000000000000000000000000000000000000..2708de32e81c6101ffcf2da807de72ee86065d4d --- /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 65c04f4e7b416016d1c43511a35342d8317c70ea..56a9bbecc72a802387748615dc6c9decb586ad73 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 1fbdb8fde5ae7ca53e834f650180306aaae0b43b..3b9460bba008f2093ac1fab71c5817e18571bd59 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 539a567acc3f534b0e0d6849a020fc3d437d4231..0dabea7d5c4ad56622e78b8e989f0f9b59000abd 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 8fdcb85f1813ca3303c4f6df09d7fe4d31e4b37d..0000000000000000000000000000000000000000 --- 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 0000000000000000000000000000000000000000..b582864ccdd17242040c91f9c57f9b8b8de171f0 --- /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 66a91dfd31390310c8078a6e051367267c8c3029..9543d6304979b166d7c2d93f64195ef39ad0f3f1 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 0de625cff88eca47d82ac3d98f292b8741b655a7..596c9d0c288769832de8ef69fa54731406d69379 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 0000000000000000000000000000000000000000..2d2058dadb43a8542930e406ad8aab17efd9b88e --- /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 0000000000000000000000000000000000000000..14d3833c2c9abb8462d36ccde12f08de68a420dd --- /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 0000000000000000000000000000000000000000..2afa6eb835035a1378ee1185dd6e36e53971534a --- /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 bb40753ca7d98a124138746d0a54b877184dc4b0..16ba4fcadf802bbcd54cd4067639b5408cfeccf3 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 6448d49d22ee5bcfdbfe0b7543b125457c93023c..a82ea5647d51fa512a3ff77084e40e732f2e3acb 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 d4fbe10cec7772556732c414ea86ae16abfe0d8a..ef3ac246287b9eb22e79cf566c1d6644524324eb 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