diff --git a/.cp/copier.yml b/.cp/copier.yml index 818a2411..688a4c62 100644 --- a/.cp/copier.yml +++ b/.cp/copier.yml @@ -103,7 +103,7 @@ ceos_lab_version: type: str help: Please select the cEOS-lab version. when: "{{ 'lab' | _in(templates) }}" - choices: ["4.32.3M"] + choices: ["4.34.2F"] clab_version: type: str diff --git a/.devcontainer/cvaas-cvaas-and-avd-demo--evpn-mlag/devcontainer.json b/.devcontainer/cvaas-cvaas-and-avd-demo--evpn-mlag/devcontainer.json index e0d478c8..5f7fef54 100644 --- a/.devcontainer/cvaas-cvaas-and-avd-demo--evpn-mlag/devcontainer.json +++ b/.devcontainer/cvaas-cvaas-and-avd-demo--evpn-mlag/devcontainer.json @@ -1,12 +1,14 @@ { - "image": "ghcr.io/${localEnv:GITHUB_REPOSITORY}/lab-base:python3.11-avd-v5.1.0-clab0.65.1-rev1.3", + // "image": "ghcr.io/${localEnv:GITHUB_REPOSITORY}/lab-base:python3.11-avd-v5.5.1-clab0.68.0-rev1.7", + "image": "ghcr.io/ankudinov/aclabs/arlabs:rev0.2", // containerEnv set the variables applied to entire container "containerEnv": { "ARISTA_TOKEN": "${localEnv:ARTOKEN}", - "CEOS_LAB_VERSION": "4.32.3M", + "CEOS_LAB_VERSION": "4.34.2F", "CV_API_TOKEN": "${localEnv:CV_API_TOKEN}", "CONTAINERWSF": "${containerWorkspaceFolder}", - "GITHUB_REPOSITORY": "${localEnv:GITHUB_REPOSITORY}" + "GITHUB_REPOSITORY": "${localEnv:GITHUB_REPOSITORY}", + "PASSWORD": "${localEnv:CODER_PASSWORD}" }, "secrets": { "CV_API_TOKEN": { @@ -28,7 +30,8 @@ "storage": "64gb" }, "onCreateCommand": "chmod +x /cvaas-cvaas-and-avd-demo--evpn-mlag/addAliases.sh; /cvaas-cvaas-and-avd-demo--evpn-mlag/addAliases.sh", - "postCreateCommand": "postCreate.sh; make start", + // "postCreateCommand": "postCreate.sh", + "postCreateCommand": "/usr/local/bin/code-server-entrypoint", "workspaceMount": "source=${localWorkspaceFolder}/labs/${containerWorkspaceFolder},target=/${containerWorkspaceFolder},type=bind", "workspaceFolder": "/cvaas-cvaas-and-avd-demo--evpn-mlag", "containerUser": "avd" diff --git a/.github/workflows/container_build_arlabs.yml b/.github/workflows/container_build_arlabs.yml new file mode 100644 index 00000000..26f9718d --- /dev/null +++ b/.github/workflows/container_build_arlabs.yml @@ -0,0 +1,25 @@ +--- +name: Create arlabs container image + +on: + push: + branches: ['**'] # branches will be filtered in the jobs + paths: + - .github/workflows/container_build_arlabs.yml + - .github/workflows/container_build_child.yml + - containers/arlabs/** + workflow_dispatch: + branches: ['**'] # branches will be filtered in the jobs + # 1 - counter to trigger build until branch is merged + +jobs: + build-demo-container: + # fork - build container from any branch for testing + # parent repo - build on main branch only + if: github.repository != 'aristanetworks/acLabs' || github.ref == 'refs/heads/main' + uses: ./.github/workflows/container_build_child.yml + with: + container_name: "arlabs" + # the rev number will be updated with each run + # image_tags: "latest,rev1.0" + image_tags: "rev0.2" diff --git a/.github/workflows/container_build_child.yml b/.github/workflows/container_build_child.yml index 5ffadf3c..38f6701b 100644 --- a/.github/workflows/container_build_child.yml +++ b/.github/workflows/container_build_child.yml @@ -111,7 +111,7 @@ jobs: - name: Pre-build dev container image 🔨 uses: devcontainers/ci@v0.3 # Only build and push the image if at least one of the image tags does not exist. - if: steps.check-image.outputs.exit_code != 0 + # if: steps.check-image.outputs.exit_code != 0 env: FROM_IMAGE: ${{ inputs.from_image }} FROM_VARIANT: ${{ inputs.from_variant }} diff --git a/.github/workflows/container_build_coder.yml b/.github/workflows/container_build_coder.yml new file mode 100644 index 00000000..22291853 --- /dev/null +++ b/.github/workflows/container_build_coder.yml @@ -0,0 +1,25 @@ +--- +name: Create Coder container image + +on: + push: + branches: ['**'] # branches will be filtered in the jobs + paths: + - .github/workflows/container_build_coder.yml + - .github/workflows/container_build_child.yml + - containers/coder/** + workflow_dispatch: + branches: ['**'] # branches will be filtered in the jobs + # 1 - counter to trigger build until branch is merged + +jobs: + build-demo-container: + # fork - build container from any branch for testing + # parent repo - build on main branch only + if: github.repository != 'aristanetworks/acLabs' || github.ref == 'refs/heads/main' + uses: ./.github/workflows/container_build_child.yml + with: + container_name: "coder" + # the rev number will be updated with each run + # image_tags: "latest,rev1.0" + image_tags: "rev1.1" diff --git a/.github/workflows/container_build_parent_matrix.yml b/.github/workflows/container_build_parent_matrix.yml index 2cfd661c..789e32df 100644 --- a/.github/workflows/container_build_parent_matrix.yml +++ b/.github/workflows/container_build_parent_matrix.yml @@ -47,4 +47,6 @@ jobs: # 1.6: # - Add AVD 5.5.1 # - Add ContainerLab 0.68.0 - container_revision: "1.6" + # 1.7: + # - add ARM support + container_revision: "1.7" diff --git a/.github/workflows/publish-pages-on-forks.yml b/.github/workflows/publish-pages-on-forks.yml index 0a68fbca..3977c79b 100644 --- a/.github/workflows/publish-pages-on-forks.yml +++ b/.github/workflows/publish-pages-on-forks.yml @@ -91,6 +91,32 @@ jobs: done rm -rf temp_labs/ + # testing lab setup for Coder image + - name: Add lab archive for coder image + run: | + mkdir site/coder_labs + mkdir temp_labs + for DEMO_DIR in labs/* + do + DEMO_NAME="${DEMO_DIR##*/}" + mkdir temp_labs/${DEMO_NAME} + mkdir temp_labs/${DEMO_NAME}/.devcontainer + mkdir temp_labs/${DEMO_NAME}/labs + cp -r .devcontainer/${DEMO_NAME}/* temp_labs/${DEMO_NAME}/.devcontainer/ + echo "adding fixes to devcontainer for coder environment" + sed -e '2d;$d' temp_labs/${DEMO_NAME}/.devcontainer/devcontainer.json > devcontainer.json + truncate -s -1 devcontainer.json + printf ',\n' >> devcontainer.json + echo ' "appPort": [8080],' >> devcontainer.json + echo ' "image": "ghcr.io/ankudinov/aclabs/coder:rev1.0"' >> devcontainer.json + echo '}' >> devcontainer.json + mv devcontainer.json temp_labs/${DEMO_NAME}/.devcontainer/devcontainer.json + cat temp_labs/${DEMO_NAME}/.devcontainer/devcontainer.json + cp -r labs/${DEMO_NAME}/ temp_labs/${DEMO_NAME}/labs/ + tar -czvf site/coder_labs/${DEMO_NAME}-coder.tar.gz --directory temp_labs/ ${DEMO_NAME} + done + rm -rf temp_labs/ + - name: Setup Pages 📖 uses: actions/configure-pages@v5 diff --git a/containers/arlabs/.devcontainer/Dockerfile b/containers/arlabs/.devcontainer/Dockerfile new file mode 100644 index 00000000..974fd303 --- /dev/null +++ b/containers/arlabs/.devcontainer/Dockerfile @@ -0,0 +1,34 @@ +ARG FROM_IMAGE +ARG FROM_VARIANT + +FROM ${FROM_IMAGE}:${FROM_VARIANT} + +ARG USERNAME + +USER root + +ENV NEW_UID="1009" +ENV NEW_GID="1009" +ENV OLD_GID="1000" +RUN sed -i -e "s/\(${USERNAME}:[^:]*:\)[^:]*:[^:]*/\1${NEW_UID}:${NEW_GID}/" /etc/passwd; \ + sed -i -e "s/\([^:]*:[^:]*:\)${OLD_GID}:/\1${NEW_GID}:/" /etc/group; \ + chown -R $NEW_UID:$NEW_GID /home/$USERNAME + +# copy code-server entrypoint +COPY ./code-server-entrypoint.sh /usr/local/bin/code-server-entrypoint +RUN chmod +x /usr/local/bin/code-server-entrypoint +ENTRYPOINT [ "/usr/local/bin/code-server-entrypoint" ] + +USER ${USERNAME} + +# install coder and extensions +RUN curl -fsSL https://code-server.dev/install.sh | sh -s -- --version="4.103.1" \ + && code-server --install-extension srl-labs.vscode-containerlab --force \ + && code-server --install-extension tuxtina.json2yaml --force + +USER root +# add global workspace settings for code-server +COPY ./settings.json /home/${USERNAME}/.local/share/code-server/User +RUN chown avd /home/${USERNAME}/.local/share/code-server/User/settings.json + +USER ${USERNAME} diff --git a/containers/arlabs/.devcontainer/code-server-entrypoint.sh b/containers/arlabs/.devcontainer/code-server-entrypoint.sh new file mode 100644 index 00000000..62bf78d0 --- /dev/null +++ b/containers/arlabs/.devcontainer/code-server-entrypoint.sh @@ -0,0 +1,133 @@ +#!/usr/bin/env bash + +set +e + +/usr/local/share/docker-init.sh + +if [ ${LAB_NAME} ]; then + cd ${CONTAINERWSF} + wget "https://ankudinov.github.io/aclabs/coder_labs/${LAB_NAME}-coder.tar.gz" + tar -xzvf ${LAB_NAME}-coder.tar.gz + rm ${LAB_NAME}-coder.tar.gz + cp -r ${LAB_NAME}/labs/${LAB_NAME}/. . + rm -rf ${LAB_NAME}/ +fi + +if [ -f "${CONTAINERWSF}/addAliases.sh" ]; then + chmod +x ${CONTAINERWSF}/addAliases.sh + ${CONTAINERWSF}/addAliases.sh +fi + +# for D-in-D case container engine will be always Docker +# however we do not want to hardcode it for future cases +if [ "$(command -v podman)" ]; then + CONTAINER_ENGINE="podman" +elif [ "$(command -v docker)" ]; then + CONTAINER_ENGINE="docker" +else + echo "ERROR: Failed to find container engine. Please install docker or podman." >&2 + exit 1 +fi + +# always prune old containers a clean lab on laptops +${CONTAINER_ENGINE} container prune -f + +# check if ceos-lab image already present +if [ -z "$(${CONTAINER_ENGINE} image ls | grep 'arista/ceos')" ]; then + if [ "${ARISTA_TOKEN}" ]; then + # `uname -m` is used to find platform architecture + # currently we check for arm64 and aarch64 and expect everything else to be an x86 machine + echo "$(uname -m)" + if [ "$(uname -m)" = "aarch64" ] || [ "$(uname -m)" = "arm64" ]; then + ardl get eos --format cEOSarm --version ${CEOS_LAB_VERSION} --import-docker + ${CONTAINER_ENGINE} tag arista/ceos:${CEOS_LAB_VERSION} arista/ceos:latest + else + ardl get eos --format cEOS --version ${CEOS_LAB_VERSION} --import-docker + ${CONTAINER_ENGINE} tag arista/ceos:${CEOS_LAB_VERSION} arista/ceos:latest + fi + # confirm that cEOS image was deleted just in case ardl failed to do that + rm -rf ${CONTAINERWSF}/cEOS*tar.xz >/dev/null 2>&1 + rm -rf ${CONTAINERWSF}/cEOS*tar.xz.sha512sum >/dev/null 2>&1 + else + # if ARISTA_TOKEN is not defined - we'll try find image in the workspace cEOS*.tar.xz + if [ -e ${CONTAINERWSF}/cEOS*tar.xz ]; then + ${CONTAINER_ENGINE} import ${CONTAINERWSF}/cEOS*tar.xz arista/ceos:latest + rm ${CONTAINERWSF}/cEOS*tar.xz + # also delete SHA if it was copied, currently we do not check if archive was broken + rm -rf ${CONTAINERWSF}/cEOS*tar.xz.sha512sum >/dev/null 2>&1 + echo "WARNING: cEOS-lab image was successfully imported from the workspace." + # also check if image was mounted to a special path + elif [ -e /img/cEOS-lab.tar.xz ]; then + ${CONTAINER_ENGINE} import /img/cEOS-lab.tar.xz arista/ceos:latest + echo "WARNING: cEOS-lab image was successfully imported from /img/cEOS-lab.tar.xz." + else + # delete any cEOS-lab files if they were copied to workspace and image was imported before + rm ${CONTAINERWSF}/cEOS*tar.xz 2>&1 + rm -rf ${CONTAINERWSF}/cEOS*tar.xz.sha512sum >/dev/null 2>&1 + echo "WARNING: arista.com token was not defined and cEOS-lab image is not present in container workspace!" + fi 2>/dev/null + fi +else + echo "WARNING: cEOS-lab image already present. Skipping the image pull/download." +fi + +if [ "${CV_API_TOKEN}" ]; then + if [ "${CVURL}" ]; then + CVTOKEN=$(curl -H "Authorization: Bearer ${CV_API_TOKEN}" "https://www.${CVURL}/api/v3/services/admin.Enrollment/AddEnrollmentToken" -d '{"enrollmentToken":{"reenrollDevices":["*"],"validFor":"24h"}}' | sed -n 's|.*"token":"\([^"]*\)".*|\1|p') + else + CVTOKEN=$(curl -H "Authorization: Bearer ${CV_API_TOKEN}" "https://www.cv-staging.corp.arista.io/api/v3/services/admin.Enrollment/AddEnrollmentToken" -d '{"enrollmentToken":{"reenrollDevices":["*"],"validFor":"24h"}}' | sed -n 's|.*"token":"\([^"]*\)".*|\1|p') + fi + if [ "${CVTOKEN}" ]; then + echo "$CVTOKEN" > ${CONTAINERWSF}/clab/cv-onboarding-token + else + echo "ERROR: failed to generate onboarding token!" + fi +else + # add default to avoid clab failing due to missing file + echo "CAFECAFE" > ${CONTAINERWSF}/clab/cv-onboarding-token +fi + +if [ -f "${CONTAINERWSF}/postCreate.sh" ]; then + chmod +x ${CONTAINERWSF}/postCreate.sh + ${CONTAINERWSF}/postCreate.sh + # delete postCreate.sh after use to avoid confusing lab user + rm ${CONTAINERWSF}/postCreate.sh +fi + +# init demo dir as Git repo if requested for this demo env +if ${GIT_INIT}; then + cd ${CONTAINERWSF} + # if not a git repo already - init + if [ -z "$(git status 2>/dev/null)" ]; then + git init + git config --global --add safe.directory ${PWD} + if [ -z "$(git config user.name)" ]; then git config user.name "Lab User"; fi + if [ -z "$(git config user.email)" ]; then git config user.email user@one-click.lab; fi + git add . + git commit -m "git init" + fi +fi + +code-server --bind-addr 0.0.0.0:8080 --auth password --disable-telemetry --disable-update-check --disable-workspace-trust "${CONTAINERWSF}" & + +# check if image is still missing and print a warning +if [ -z "$(${CONTAINER_ENGINE} image ls | grep 'arista/ceos')" ]; then + echo "WARNING: cEOS-lab image download failed. Try to upload and import it manually." + echo " Please make sure that image is imported with a correct name - arista/ceos:latest" + echo " The lab will not auto start! Run 'make start' when image is ready." +else + cd ${CONTAINERWSF} + make start +fi + +# Execute command from docker cli if any. +if [ ${@+True} ]; then + exec "$@" +# Otherwise just enter sh or zsh. +else + if [ -f "/bin/zsh" ]; then + exec zsh + else + exec sh + fi +fi diff --git a/containers/arlabs/.devcontainer/devcontainer.json b/containers/arlabs/.devcontainer/devcontainer.json new file mode 100644 index 00000000..bae27b37 --- /dev/null +++ b/containers/arlabs/.devcontainer/devcontainer.json @@ -0,0 +1,17 @@ +{ + "build": { + "dockerfile": "Dockerfile", + "args": { + // "FROM_IMAGE": "${localEnv:FROM_IMAGE}", + "FROM_IMAGE": "ghcr.io/ankudinov/aclabs/lab-base", + // "FROM_VARIANT": "${localEnv:FROM_VARIANT}", + "FROM_VARIANT": "python3.11-avd-v5.5.1-clab0.68.0-rev1.7", + // "USERNAME": "${localEnv:USERNAME}", + "USERNAME": "avd" + } + }, + // "forwardPorts": ["localhost:8080"], + // "appPort": [8080], + // "overrideCommand": false, + "containerUser": "avd" +} \ No newline at end of file diff --git a/containers/arlabs/.devcontainer/settings.json b/containers/arlabs/.devcontainer/settings.json new file mode 100644 index 00000000..97dfc0bc --- /dev/null +++ b/containers/arlabs/.devcontainer/settings.json @@ -0,0 +1,3 @@ +{ + "workbench.startupEditor": "readme" +} \ No newline at end of file diff --git a/containers/coder/.devcontainer/Dockerfile b/containers/coder/.devcontainer/Dockerfile new file mode 100644 index 00000000..2b43f3cd --- /dev/null +++ b/containers/coder/.devcontainer/Dockerfile @@ -0,0 +1,20 @@ +ARG FROM_IMAGE +ARG FROM_VARIANT + +FROM ${FROM_IMAGE}:${FROM_VARIANT} + +ARG USERNAME + +USER root + +# copy code-server entrypoint +COPY ./code-server-entrypoint.sh /usr/local/bin/code-server-entrypoint +RUN chmod +x /usr/local/bin/code-server-entrypoint +ENTRYPOINT [ "/usr/local/bin/code-server-entrypoint" ] + +USER ${USERNAME} + +# install coder and extensions +RUN curl -fsSL https://code-server.dev/install.sh | sh -s -- --version="4.103.1" \ + && code-server --install-extension srl-labs.vscode-containerlab --force \ + && code-server --install-extension tuxtina.json2yaml --force diff --git a/containers/coder/.devcontainer/code-server-entrypoint.sh b/containers/coder/.devcontainer/code-server-entrypoint.sh new file mode 100644 index 00000000..6ad12e0d --- /dev/null +++ b/containers/coder/.devcontainer/code-server-entrypoint.sh @@ -0,0 +1,163 @@ +#!/usr/bin/env bash + +set +e + +REMOTE_USER="avd" +OLD_GID="1000" +if [ ${NEW_UID} ]; then + sudo sed -i -e "s/\(${REMOTE_USER}:[^:]*:\)[^:]*:[^:]*/\1${NEW_UID}:${NEW_GID}/" /etc/passwd; + sudo sed -i -e "s/\([^:]*:[^:]*:\)${OLD_GID}:/\1${NEW_GID}:/" /etc/group; + sudo chown -R $NEW_UID:$NEW_GID $CONTAINERWSF; + sudo chown -R $NEW_UID:$NEW_GID $HOME; +fi + +/usr/local/share/docker-init.sh + +if [ ${LAB_NAME} ]; then + cd ${CONTAINERWSF} + wget "https://ankudinov.github.io/aclabs/coder_labs/${LAB_NAME}-coder.tar.gz" + tar -xzvf ${LAB_NAME}-coder.tar.gz + rm ${LAB_NAME}-coder.tar.gz + cp -r ${LAB_NAME}/labs/${LAB_NAME}/. . + rm -rf ${LAB_NAME}/ +fi + +if [ -f "${CONTAINERWSF}/addAliases.sh" ]; then + chmod +x ${CONTAINERWSF}/addAliases.sh + ${CONTAINERWSF}/addAliases.sh +fi + +# replace all markdown vars in demo directory +if [ "${GITHUB_REPOSITORY}" ]; then + grep -rl '{{gh.repo_name}}' . --exclude-dir .git | xargs sed -i 's/{{gh.repo_name}}/'"${GITHUB_REPOSITORY##*/}"'/g' + grep -rl '{{gh.org_name}}' . --exclude-dir .git | xargs sed -i 's/{{gh.org_name}}/'"${GITHUB_REPOSITORY%%/*}"'/g' + grep -rl '{{gh.repository}}' . --exclude-dir .git | xargs sed -i 's@{{gh.repository}}@'"${GITHUB_REPOSITORY}"'@g' +else + # if not running on Codespaces and GITHUB_REPOSITORY is not set - set aristanetworks/acLabs by default + grep -rl '{{gh.repo_name}}' . --exclude-dir .git | xargs sed -i 's/{{gh.repo_name}}/'"acLabs"'/g' + grep -rl '{{gh.org_name}}' . --exclude-dir .git | xargs sed -i 's/{{gh.org_name}}/'"aristanetworks"'/g' + grep -rl '{{gh.repository}}' . --exclude-dir .git | xargs sed -i 's@{{gh.repository}}@'"aristanetworks/acLabs"'@g' +fi +# update URL in clab init configs if set +if [ "${CVURL}" ]; then + grep -rl '{{cv_url}}' . --exclude-dir .git | xargs sed -i 's@{{cv_url}}@'"${CVURL}"'@g' + # check for legacy labs using hardcoded URL + grep -rl 'cv-staging.corp.arista.io' . --exclude-dir .git | xargs sed -i 's@cv-staging.corp.arista.io@'"${CVURL}"'@g' +else + # set defaul url to staging if nothing is defined + grep -rl '{{cv_url}}' . --exclude-dir .git | xargs sed -i 's@{{cv_url}}@'"cv-staging.corp.arista.io"'@g' +fi + +# for D-in-D case container engine will be always Docker +# however we do not want to hardcode it for future cases +if [ "$(command -v podman)" ]; then + CONTAINER_ENGINE="podman" +elif [ "$(command -v docker)" ]; then + CONTAINER_ENGINE="docker" +else + echo "ERROR: Failed to find container engine. Please install docker or podman." >&2 + exit 1 +fi + +# always prune old containers a clean lab on laptops +${CONTAINER_ENGINE} container prune -f + +# check if ceos-lab image already present +if [ -z "$(${CONTAINER_ENGINE} image ls | grep 'arista/ceos')" ]; then + if [ "${ARISTA_TOKEN}" ]; then + # `uname -m` is used to find platform architecture + # currently we check for arm64 and aarch64 and expect everything else to be an x86 machine + echo "$(uname -m)" + if [ "$(uname -m)" = "aarch64" ] || [ "$(uname -m)" = "arm64" ]; then + ardl get eos --format cEOSarm --version ${CEOS_LAB_VERSION} --import-docker + ${CONTAINER_ENGINE} tag arista/ceos:${CEOS_LAB_VERSION} arista/ceos:latest + else + ardl get eos --format cEOS --version ${CEOS_LAB_VERSION} --import-docker + ${CONTAINER_ENGINE} tag arista/ceos:${CEOS_LAB_VERSION} arista/ceos:latest + fi + # confirm that cEOS image was deleted just in case ardl failed to do that + rm -rf ${CONTAINERWSF}/cEOS*tar.xz >/dev/null 2>&1 + rm -rf ${CONTAINERWSF}/cEOS*tar.xz.sha512sum >/dev/null 2>&1 + else + # if ARISTA_TOKEN is not defined - we'll try find image in the workspace cEOS*.tar.xz + if [ -e ${CONTAINERWSF}/cEOS*tar.xz ]; then + ${CONTAINER_ENGINE} import ${CONTAINERWSF}/cEOS*tar.xz arista/ceos:latest + rm ${CONTAINERWSF}/cEOS*tar.xz + # also delete SHA if it was copied, currently we do not check if archive was broken + rm -rf ${CONTAINERWSF}/cEOS*tar.xz.sha512sum >/dev/null 2>&1 + echo "WARNING: cEOS-lab image was successfully imported from the workspace." + # also check if image was mounted to a special path + elif [ -e /img/cEOS-lab.tar.xz ]; then + ${CONTAINER_ENGINE} import /img/cEOS-lab.tar.xz arista/ceos:latest + echo "WARNING: cEOS-lab image was successfully imported from /img/cEOS-lab.tar.xz." + else + # delete any cEOS-lab files if they were copied to workspace and image was imported before + rm ${CONTAINERWSF}/cEOS*tar.xz 2>&1 + rm -rf ${CONTAINERWSF}/cEOS*tar.xz.sha512sum >/dev/null 2>&1 + echo "WARNING: arista.com token was not defined and cEOS-lab image is not present in container workspace!" + fi 2>/dev/null + fi +else + echo "WARNING: cEOS-lab image already present. Skipping the image pull/download." +fi + +if [ "${CV_API_TOKEN}" ]; then + if [ "${CVURL}" ]; then + CVTOKEN=$(curl -H "Authorization: Bearer ${CV_API_TOKEN}" "https://www.${CVURL}/api/v3/services/admin.Enrollment/AddEnrollmentToken" -d '{"enrollmentToken":{"reenrollDevices":["*"],"validFor":"24h"}}' | sed -n 's|.*"token":"\([^"]*\)".*|\1|p') + else + CVTOKEN=$(curl -H "Authorization: Bearer ${CV_API_TOKEN}" "https://www.cv-staging.corp.arista.io/api/v3/services/admin.Enrollment/AddEnrollmentToken" -d '{"enrollmentToken":{"reenrollDevices":["*"],"validFor":"24h"}}' | sed -n 's|.*"token":"\([^"]*\)".*|\1|p') + fi + if [ "${CVTOKEN}" ]; then + echo "$CVTOKEN" > ${CONTAINERWSF}/clab/cv-onboarding-token + else + echo "ERROR: failed to generate onboarding token!" + fi +else + # add default to avoid clab failing due to missing file + echo "CAFECAFE" > ${CONTAINERWSF}/clab/cv-onboarding-token +fi + +if [ -f "${CONTAINERWSF}/postCreate.sh" ]; then + chmod +x ${CONTAINERWSF}/postCreate.sh + ${CONTAINERWSF}/postCreate.sh + # delete postCreate.sh after use to avoid confusing lab user + rm ${CONTAINERWSF}/postCreate.sh +fi + +# init demo dir as Git repo if requested for this demo env +if ${GIT_INIT}; then + cd ${CONTAINERWSF} + # if not a git repo already - init + if [ -z "$(git status 2>/dev/null)" ]; then + git init + git config --global --add safe.directory ${PWD} + if [ -z "$(git config user.name)" ]; then git config user.name "Lab User"; fi + if [ -z "$(git config user.email)" ]; then git config user.email user@one-click.lab; fi + git add . + git commit -m "git init" + fi +fi + +code-server --bind-addr 0.0.0.0:8080 --auth password --disable-telemetry --disable-update-check --disable-workspace-trust "${CONTAINERWSF}" & + +# check if image is still missing and print a warning +if [ -z "$(${CONTAINER_ENGINE} image ls | grep 'arista/ceos')" ]; then + echo "WARNING: cEOS-lab image download failed. Try to upload and import it manually." + echo " Please make sure that image is imported with a correct name - arista/ceos:latest" + echo " The lab will not auto start! Run 'make start' when image is ready." +else + cd ${CONTAINERWSF} + make start +fi + +# Execute command from docker cli if any. +if [ ${@+True} ]; then + exec "$@" +# Otherwise just enter sh or zsh. +else + if [ -f "/bin/zsh" ]; then + exec zsh + else + exec sh + fi +fi diff --git a/containers/coder/.devcontainer/devcontainer.json b/containers/coder/.devcontainer/devcontainer.json new file mode 100644 index 00000000..91ec28f4 --- /dev/null +++ b/containers/coder/.devcontainer/devcontainer.json @@ -0,0 +1,17 @@ +{ + "build": { + "dockerfile": "Dockerfile", + "args": { + // "FROM_IMAGE": "${localEnv:FROM_IMAGE}", + "FROM_IMAGE": "ghcr.io/ankudinov/aclabs/lab-base", + // "FROM_VARIANT": "${localEnv:FROM_VARIANT}", + "FROM_VARIANT": "python3.11-avd-v5.5.1-clab0.68.0-rev1.7", + // "USERNAME": "${localEnv:USERNAME}", + "USERNAME": "avd" + } + }, + // "forwardPorts": ["localhost:8080"], + "appPort": [8080], + "overrideCommand": false, + "containerUser": "avd" +} \ No newline at end of file diff --git a/containers/lab-base/.devcontainer/postCreate.sh b/containers/lab-base/.devcontainer/postCreate.sh index b831edb9..424a684a 100644 --- a/containers/lab-base/.devcontainer/postCreate.sh +++ b/containers/lab-base/.devcontainer/postCreate.sh @@ -23,8 +23,54 @@ else grep -rl '{{cv_url}}' . --exclude-dir .git | xargs sed -i 's@{{cv_url}}@'"cv-staging.corp.arista.io"'@g' fi -ardl get eos --format cEOS64 --version ${CEOS_LAB_VERSION} --import-docker -docker tag arista/ceos:${CEOS_LAB_VERSION} arista/ceos:latest +# for D-in-D case container engine will be always Docker +# however we do not want to hardcode it for future cases +if [ "$(command -v podman)" ]; then + CONTAINER_ENGINE="podman" +elif [ "$(command -v docker)" ]; then + CONTAINER_ENGINE="docker" +else + echo "ERROR: Failed to find container engine. Please install docker or podman." >&2 + exit 1 +fi + +# always prune old containers a clean lab on laptops +${CONTAINER_ENGINE} container prune -f + +# check if ceos-lab image already present +if [ -z "$(${CONTAINER_ENGINE} image ls | grep 'arista/ceos')" ]; then + if [ "${ARISTA_TOKEN}" ]; then + # `uname -m` is used to find platform architecture + # currently we check for arm64 and aarch64 and expect everything else to be an x86 machine + echo "$(uname -m)" + if [ "$(uname -m)" = "aarch64" ] || [ "$(uname -m)" = "arm64" ]; then + ardl get eos --format cEOSarm --version ${CEOS_LAB_VERSION} --import-docker + ${CONTAINER_ENGINE} tag arista/ceos:${CEOS_LAB_VERSION} arista/ceos:latest + else + ardl get eos --format cEOS --version ${CEOS_LAB_VERSION} --import-docker + ${CONTAINER_ENGINE} tag arista/ceos:${CEOS_LAB_VERSION} arista/ceos:latest + fi + # confirm that cEOS image was deleted just in case ardl failed to do that + rm -rf ${CONTAINERWSF}/cEOS*tar.xz >/dev/null 2>&1 + rm -rf ${CONTAINERWSF}/cEOS*tar.xz.sha512sum >/dev/null 2>&1 + else + # if ARISTA_TOKEN is not defined - we'll try find image in the workspace cEOS*.tar.xz + if [ -e ${CONTAINERWSF}/cEOS*tar.xz ]; then + ${CONTAINER_ENGINE} import ${CONTAINERWSF}/cEOS*tar.xz arista/ceos:latest + rm ${CONTAINERWSF}/cEOS*tar.xz + # also delete SHA if it was copied, currently we do not check if archive was broken + rm -rf ${CONTAINERWSF}/cEOS*tar.xz.sha512sum >/dev/null 2>&1 + echo "WARNING: cEOS-lab image was successfully imported from the workspace." + else + # delete any cEOS-lab files if they were copied to workspace and image was imported before + rm ${CONTAINERWSF}/cEOS*tar.xz 2>&1 + rm -rf ${CONTAINERWSF}/cEOS*tar.xz.sha512sum >/dev/null 2>&1 + echo "WARNING: arista.com token was not defined and cEOS-lab image is not present in container workspace!" + fi 2>/dev/null + fi +else + echo "WARNING: cEOS-lab image already present. Skipping the image pull/download." +fi if [ "${CV_API_TOKEN}" ]; then if [ "${CVURL}" ]; then @@ -32,7 +78,14 @@ if [ "${CV_API_TOKEN}" ]; then else CVTOKEN=$(curl -H "Authorization: Bearer ${CV_API_TOKEN}" "https://www.cv-staging.corp.arista.io/api/v3/services/admin.Enrollment/AddEnrollmentToken" -d '{"enrollmentToken":{"reenrollDevices":["*"],"validFor":"24h"}}' | sed -n 's|.*"token":"\([^"]*\)".*|\1|p') fi - echo "$CVTOKEN" > ${CONTAINERWSF}/clab/cv-onboarding-token + if [ "${CVTOKEN}" ]; then + echo "$CVTOKEN" > ${CONTAINERWSF}/clab/cv-onboarding-token + else + echo "ERROR: failed to generate onboarding token!" + fi +else + # add default to avoid clab failing due to missing file + echo "CAFECAFE" > ${CONTAINERWSF}/clab/cv-onboarding-token fi if [ -f "${CONTAINERWSF}/postCreate.sh" ]; then @@ -55,3 +108,12 @@ if ${GIT_INIT}; then git commit -m "git init" fi fi + +# check if image is still missing and print a warning +if [ -z "$(${CONTAINER_ENGINE} image ls | grep 'arista/ceos')" ]; then + echo "WARNING: cEOS-lab image download failed. Try to upload and import it manually." + echo " Please make sure that image is imported with a correct name - arista/ceos:latest" + echo " The lab will not auto start! Run 'make start' when image is ready." +else + make start +fi diff --git a/docs/cvaas-cvaas-and-avd-demo--evpn-mlag.md b/docs/cvaas-cvaas-and-avd-demo--evpn-mlag.md index ea6bae58..a7632aa4 100644 --- a/docs/cvaas-cvaas-and-avd-demo--evpn-mlag.md +++ b/docs/cvaas-cvaas-and-avd-demo--evpn-mlag.md @@ -48,14 +48,14 @@ This lab has following devices: | Hostname | Type | OS | Management Address | Username | Password | | -------- | ---- | -- | ------------------ | -------- | -------- | -| s01 | switch | cEOS-lab, 4.32.3M | 10.0.1.1 | arista | arista | -| s02 | switch | cEOS-lab, 4.32.3M | 10.0.1.2 | arista | arista | -| l01 | switch | cEOS-lab, 4.32.3M | 10.0.2.1 | arista | arista | -| l02 | switch | cEOS-lab, 4.32.3M | 10.0.2.2 | arista | arista | -| l03 | switch | cEOS-lab, 4.32.3M | 10.0.2.3 | arista | arista | -| l04 | switch | cEOS-lab, 4.32.3M | 10.0.2.4 | arista | arista | -| h01 | host | cEOS-lab, 4.32.3M | 10.0.3.1 | arista | arista | -| h02 | host | cEOS-lab, 4.32.3M | 10.0.3.2 | arista | arista | +| s01 | switch | cEOS-lab, 4.34.2F | 10.0.1.1 | arista | arista | +| s02 | switch | cEOS-lab, 4.34.2F | 10.0.1.2 | arista | arista | +| l01 | switch | cEOS-lab, 4.34.2F | 10.0.2.1 | arista | arista | +| l02 | switch | cEOS-lab, 4.34.2F | 10.0.2.2 | arista | arista | +| l03 | switch | cEOS-lab, 4.34.2F | 10.0.2.3 | arista | arista | +| l04 | switch | cEOS-lab, 4.34.2F | 10.0.2.4 | arista | arista | +| h01 | host | cEOS-lab, 4.34.2F | 10.0.3.1 | arista | arista | +| h02 | host | cEOS-lab, 4.34.2F | 10.0.3.2 | arista | arista | > To access any device, use `ssh @` or simply type `` to use the SSH alias. diff --git a/labs/cvaas-cvaas-and-avd-demo--evpn-mlag/.vscode/settings.json b/labs/cvaas-cvaas-and-avd-demo--evpn-mlag/.vscode/settings.json new file mode 100644 index 00000000..d0cf70d8 --- /dev/null +++ b/labs/cvaas-cvaas-and-avd-demo--evpn-mlag/.vscode/settings.json @@ -0,0 +1,11 @@ +{ + "workbench.startupEditor": "readme", + "containerlab": { + "showWelcomePage": false, + "node": { + "sshUserMapping": { + "ceos": "arista" + } + } + } +} \ No newline at end of file diff --git a/labs/cvaas-cvaas-and-avd-demo--evpn-mlag/README.md b/labs/cvaas-cvaas-and-avd-demo--evpn-mlag/README.md index 2009a6f1..08b05522 100644 --- a/labs/cvaas-cvaas-and-avd-demo--evpn-mlag/README.md +++ b/labs/cvaas-cvaas-and-avd-demo--evpn-mlag/README.md @@ -2,7 +2,7 @@ This lab is tested for: - cEOS-lab version: 4.32.3M + cEOS-lab version: 4.34.2F Containerlab Version: 0.61.0 Codespace Container Size CPUs: 8 @@ -27,13 +27,13 @@ This lab has following devices: | Hostname | Type | OS | Management Address | Username | Password | | -------- | ---- | -- | ------------------ | -------- | -------- | -| s01 | switch | cEOS-lab, 4.32.3M | 10.0.1.1 | arista | arista | -| s02 | switch | cEOS-lab, 4.32.3M | 10.0.1.2 | arista | arista | -| l01 | switch | cEOS-lab, 4.32.3M | 10.0.2.1 | arista | arista | -| l02 | switch | cEOS-lab, 4.32.3M | 10.0.2.2 | arista | arista | -| l03 | switch | cEOS-lab, 4.32.3M | 10.0.2.3 | arista | arista | -| l04 | switch | cEOS-lab, 4.32.3M | 10.0.2.4 | arista | arista | -| h01 | host | cEOS-lab, 4.32.3M | 10.0.3.1 | arista | arista | -| h02 | host | cEOS-lab, 4.32.3M | 10.0.3.2 | arista | arista | +| s01 | switch | cEOS-lab, 4.34.2F | 10.0.1.1 | arista | arista | +| s02 | switch | cEOS-lab, 4.34.2F | 10.0.1.2 | arista | arista | +| l01 | switch | cEOS-lab, 4.34.2F | 10.0.2.1 | arista | arista | +| l02 | switch | cEOS-lab, 4.34.2F | 10.0.2.2 | arista | arista | +| l03 | switch | cEOS-lab, 4.34.2F | 10.0.2.3 | arista | arista | +| l04 | switch | cEOS-lab, 4.34.2F | 10.0.2.4 | arista | arista | +| h01 | host | cEOS-lab, 4.34.2F | 10.0.3.1 | arista | arista | +| h02 | host | cEOS-lab, 4.34.2F | 10.0.3.2 | arista | arista | > To access any device, use `ssh @` or simply type `` to use the SSH alias. diff --git a/labs/cvaas-cvaas-and-avd-demo--evpn-mlag/clab/topology.clab.yml b/labs/cvaas-cvaas-and-avd-demo--evpn-mlag/clab/topology.clab.yml index 91b8e60e..757c72b0 100644 --- a/labs/cvaas-cvaas-and-avd-demo--evpn-mlag/clab/topology.clab.yml +++ b/labs/cvaas-cvaas-and-avd-demo--evpn-mlag/clab/topology.clab.yml @@ -26,37 +26,69 @@ topology: binds: - sn/s01.txt:/mnt/flash/ceos-config:ro startup-config: init-configs/s01.cfg + labels: + topoViewer-role: spine + graph-group: "Data Center Spine" + graph-level: "1" s02: mgmt-ipv4: 10.0.1.2 binds: - sn/s02.txt:/mnt/flash/ceos-config:ro startup-config: init-configs/s02.cfg + labels: + topoViewer-role: spine + graph-group: "Data Center Spine" + graph-level: "1" l01: mgmt-ipv4: 10.0.2.1 binds: - sn/l01.txt:/mnt/flash/ceos-config:ro startup-config: init-configs/l01.cfg + labels: + topoViewer-role: leaf + graph-group: "Data Center Leaf" + graph-level: "2" l02: mgmt-ipv4: 10.0.2.2 binds: - sn/l02.txt:/mnt/flash/ceos-config:ro startup-config: init-configs/l02.cfg + labels: + topoViewer-role: leaf + graph-group: "Data Center Leaf" + graph-level: "2" l03: mgmt-ipv4: 10.0.2.3 binds: - sn/l03.txt:/mnt/flash/ceos-config:ro startup-config: init-configs/l03.cfg + labels: + topoViewer-role: leaf + graph-group: "Data Center Leaf" + graph-level: "2" l04: mgmt-ipv4: 10.0.2.4 binds: - sn/l04.txt:/mnt/flash/ceos-config:ro startup-config: init-configs/l04.cfg + labels: + topoViewer-role: leaf + graph-group: "Data Center Leaf" + graph-level: "2" h01: mgmt-ipv4: 10.0.3.1 startup-config: init-configs/h01.cfg + labels: + topoViewer-role: host + graph-group: "Data Center Host" + graph-level: "3" h02: mgmt-ipv4: 10.0.3.2 startup-config: init-configs/h02.cfg + labels: + topoViewer-role: host + graph-group: "Data Center Host" + graph-level: "3" links: - endpoints: ["l01:eth1", "s01:eth1"]