Skip to content

Commit

Permalink
Feat: AVD dev containers (#3179)
Browse files Browse the repository at this point in the history
Co-authored-by: Ryan Chetcuti <[email protected]>
Co-authored-by: Guillaume Mulocher <[email protected]>
Co-authored-by: Claus Holbech <[email protected]>
  • Loading branch information
4 people authored Nov 9, 2023
1 parent d8f83f3 commit b09b52a
Show file tree
Hide file tree
Showing 19 changed files with 614 additions and 83 deletions.
96 changes: 14 additions & 82 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,86 +1,18 @@
{
"name": "AVD Development",
"build": {
"dockerfile": "Dockerfile",
"args": { "VARIANT": "3.8-v2.0" },
},
"remoteUser": "avd",
"updateRemoteUserUID": true,
"workspaceMount": "source=${localWorkspaceFolder}/..,target=/workspace,type=bind,consistency=delegated",
"workspaceFolder": "/workspace",
"extensions": [
"christian-kohler.path-intellisense",
"codezombiech.gitignore",
"DavidAnson.vscode-markdownlint",
"donjayamanne.python-extension-pack",
"eamodio.gitlens",
"felipe-mendes.slack-theme",
"haaaad.ansible",
"jack89ita.copy-filename",
"jdinhlife.gruvbox",
"jebbs.markdown-extended",
"magicstack.MagicPython",
"mhutchie.git-graph",
"ms-python.python",
"ms-toolsai.jupyter",
"njpwerner.autodocstring",
"PKief.material-icon-theme",
"redhat.vscode-yaml",
"samuelcolvin.jinjahtml",
"timonwong.ansible-autocomplete",
"tuxtina.json2yaml",
"wholroyd.jinja",
"yzhang.markdown-all-in-one",
"coenraads.bracket-pair-colorizer-2",
"github.vscode-pull-request-github",
"ms-python.vscode-pylance"
"mounts": [
"source=${localWorkspaceFolder}/ansible_collections/arista/avd,target=/home/avd/.ansible/collections/ansible_collections/arista/avd,type=bind"
],
"settings": {
"python.pythonPath": "/usr/local/bin/python",
"python.analysis.extraPaths": [
"/workspace/"
],
"python.linting.pylintEnabled": true,
"python.linting.enabled": true,
"editor.rulers": [
80,
120
],
"editor.formatOnPaste": true,
"files.trimTrailingWhitespace": true,
"python.linting.pycodestyleEnabled": false,
"python.linting.pycodestyleArgs": [
"--max-line-length=120",
"--ignore=E501,722"
],
"python.linting.flake8Enabled": true,
"python.linting.flake8Args": [
"--max-line-length=120",
"--ignore=E722,E501",
"--verbose",
"--exclude=*.pyc *.git",
"--format=pylint"
],
"python.linting.pylintArgs": [
"--max-line-length=120",
"--disable=E501,W0142,W0403,W0613,W0232,R0903,R0913,C0103,R0914,C0304,F0401,W0402,E1101,W0614,C0111,C0301"
],
"autoDocstring.startOnNewLine": true,
"telemetry.enableCrashReporter": false,
"telemetry.enableTelemetry": false,
"gitlens.views.repositories.location": "scm",
"gitlens.views.fileHistory.location": "explorer",
"gitlens.views.lineHistory.location": "explorer",
"gitlens.views.search.location": "scm",
"gitlens.views.compare.location": "scm",
"gitlens.views.repositories.files.layout": "tree",
"editor.renderWhitespace": "all",
"files.autoSave": "onFocusChange",
"autoDocstring.includeName": true,
"autoDocstring.docstringFormat": "numpy",
"autoDocstring.includeExtendedSummary": true,
"path-intellisense.autoSlashAfterDirectory": true,
"editor.find.autoFindInSelection": "multiline",
"githubIssues.issueBranchTitle": "issues/${issueNumber}"
}
"image": "ghcr.io/aristanetworks/ansible-avd/dev:python3.11-avd-devel",
// The AVD collection can also be installed from any git branch.
// Comment mount section if this is the case.
//
// "containerEnv": {
// "AVD_GITHUB_REPO": "aristanetworks/ansible-avd",
// "AVD_BRANCH_NAME": "devel"
// },
// Run entrypoint script manually as it's ignored by dev container CLI otherwise.
// The dev entrypoint is used to install Ansible collections and requirements, as they are not included with the dev version.
// "true" is required to exit "onCreateCommand" without entering ZSH.
"onCreateCommand": "/bin/entrypoint.sh true"
}
1 change: 1 addition & 0 deletions .github/generate_release.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"eos_validate_state",
"plugins",
"requirements",
"containers",
# Handle multiple scopes ',' are not supported in Github labels and so replaced with '|' by our action
"eos_designs|eos_cli_config_gen",
"eos_cli_config_gen|eos_designs",
Expand Down
29 changes: 29 additions & 0 deletions .github/workflows/container_build_base.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
name: Build base container

on:
push:
branches:
- devel
paths:
- avd-containers/base/**
- .github/workflows/container_build_template.yml
- .github/workflows/container_build_base.yml
workflow_dispatch:
branches:
- devel

jobs:
build_base:
uses: ./.github/workflows/container_build_template.yml
strategy:
matrix:
container_name: [base]
python_version: ["3.9", "3.10", "3.11"]
include:
- python_version: "3.11"
container_tags: latest
with:
container_name: ${{ matrix.container_name }}
python_version: ${{ matrix.python_version }}
container_tags: ${{ matrix.container_tags }}
29 changes: 29 additions & 0 deletions .github/workflows/container_build_dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
name: Build dev container

on:
push:
branches:
- devel
paths:
- avd-containers/dev/**
- .github/workflows/container_build_template.yml
- .github/workflows/container_build_dev.yml
workflow_dispatch:
branches:
- devel

jobs:
build_dev_container:
uses: ./.github/workflows/container_build_template.yml
strategy:
matrix:
container_name: [dev]
python_version: ["3.9", "3.10", "3.11"]
include:
- python_version: "3.11"
container_tags: latest
with:
container_name: ${{ matrix.container_name }}
python_version: ${{ matrix.python_version }}
container_tags: ${{ matrix.container_tags }}
189 changes: 189 additions & 0 deletions .github/workflows/container_build_template.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
---
# This workflow file is the template
# that will be triggered by specific container build workflows.

name: Reusable build container workflow

env:
# BUILDX_NO_DEFAULT_ATTESTATIONS must be set to build only arm64 and amd64 images.
# The devcontainers/[email protected] build will fail if this env variable is not set.
BUILDX_NO_DEFAULT_ATTESTATIONS: 1

on:
workflow_call:
inputs:
# Container name, e.g. "base", "dev", etc.
container_name:
required: true
type: string
# Container tags, e.g. "latest,python3.11" or "latest,python3.11-avd4.1.0".
# Container tags are optional as they are auto-generated if not provided.
container_tags:
required: false
type: string
# Platform, e.g. "linux/amd64", "linux/arm64/v8".
# "default" is just fine if there is no intention to release a special build.
platform:
required: false
type: string
default: linux/arm64/v8,linux/amd64
# From image, e.g. "python", "alpine", etc.
# Currently we only support python-slim, so this is a future knob.
from_image:
required: false
type: string
default: python
# From variant, e.g. "3.11-slim-bullseye".
# This is auto-generated for python-slim based builds.
# Only specify for special builds.
from_variant:
required: false
type: string
username:
required: false
type: string
default: avd
user_id:
required: false
type: string
default: 1000
group_id:
required: false
type: string
default: 1000
python_version:
required: true
type: string

jobs:
build_image:
runs-on: ubuntu-22.04
steps:
- name: Starting container build
run: echo "Starting container build. Be patient. 🐢"
- name: Checkout code ✅
uses: actions/checkout@v4
# Build image tags based on Python version and AVD version (if defined).
# If container_tags is not defined, then image_tags will be auto-generated.
# If container_tags is latest, it will be added to auto-generated image_tags.
# If container_tags is defined and not latest, it will be used as-is.
- name: Build image tags 🏷️
id: build-tags
run: |
if [ -z "${{ inputs.container_tags }}" ]; then
case ${{ inputs.container_name }} in
base)
echo "image_tags=python${{ inputs.python_version }}" >> $GITHUB_OUTPUT
;;
dev)
echo "image_tags=python${{ inputs.python_version }}" >> $GITHUB_OUTPUT
;;
*)
echo "image_tags=python${{ inputs.python_version }}-avd-${{ github.ref_name }}" >> $GITHUB_OUTPUT
;;
esac
else
if [ "${{ inputs.container_tags }}" == "latest" ]; then
case ${{ inputs.container_name }} in
base)
echo "image_tags=latest,python${{ inputs.python_version }}" >> $GITHUB_OUTPUT
;;
dev)
echo "image_tags=latest,python${{ inputs.python_version }}" >> $GITHUB_OUTPUT
;;
*)
echo "image_tags=latest,python${{ inputs.python_version }}-avd-${{ github.ref_name }}" >> $GITHUB_OUTPUT
;;
esac
else
echo "image_tags=${{ inputs.container_tags }}" >> $GITHUB_OUTPUT
fi
fi
- name: Generate from_image and from_variant parameters 🐍
id: generate-from-parameters
# Logic:
# 1) Only python-slim images are supported at the moment.
# 2) Base image must be built first from official python image.
# 3) All other images will be built from the base image.
# 4) "from_image" and "from_variant" can be passed transparently to the build step,
# but that is not implemented currently.
run: |
if [ "${{ inputs.from_image }}" == "python" ]; then
if [ "${{ inputs.container_name }}" == "base" ]; then
echo "from_image=${{ inputs.from_image }}" >> $GITHUB_OUTPUT
echo "from_variant=${{ inputs.python_version }}-slim-bullseye" >> $GITHUB_OUTPUT
else
echo "from_image=ghcr.io/${{ github.repository }}/base" >> $GITHUB_OUTPUT
echo "from_variant=python${{ inputs.python_version }}" >> $GITHUB_OUTPUT
fi
else
echo "Only python-slim images are supported at the moment. Exiting."
exit 1
fi
- name: Find ansible-core version 🔥
id: find-ansible-core-version
run: |
ANSIBLE_CORE_VERSION=$(cat ansible_collections/arista/avd/requirements-dev.txt| grep ansible-core)
echo "ansible_core_version=$ANSIBLE_CORE_VERSION" >> $GITHUB_OUTPUT
- name: Find ansible install location
id: find-ansible-install-location
run: |
ANSIBLE_INSTALL_LOCATION="git+https://github.com/${{ github.repository }}.git#/ansible_collections/arista/avd/,${{ github.ref_name }}"
echo "ansible_install_location=$ANSIBLE_INSTALL_LOCATION" >> $GITHUB_OUTPUT
# This check is temporarily deactivated, will be rewised in later PRs
#
# - name: Check if image is already present
# # this step will check if image was already pushed before to avoid re-writing
# # also if it's not a base image, this step will verify presence of the corresponding base image
# id: check-image-presence
# run: |
# echo "not_present=0" >> $GITHUB_OUTPUT
# for tag in $(echo ${{ steps.build-tags.outputs.image_tags }} | sed "s/,/ /g")
# do
# ( docker manifest inspect ghcr.io/${{ github.repository }}/${{ inputs.container_name }}:${tag} &>/dev/null ) || echo "not_present=1" >> $GITHUB_OUTPUT
# done
# # check if base image is present
# if [ "${{ inputs.container_name }}" != "base" ]; then
# echo "Verifying if base image is present..."
# docker manifest inspect ghcr.io/${{ github.repository }}/base:python${{ inputs.python_version }} >/dev/null
# fi

- name: Setup QEMU for multi-arch builds 🏗️
# if: ${{ steps.check-image-presence.outputs.not_present == '1' }}
uses: docker/setup-qemu-action@v3
with:
platforms: ${{ inputs.platform }}

- name: Setup Docker buildX for multi-arch builds 🏗️
# if: ${{ steps.check-image-presence.outputs.not_present == '1' }}
uses: docker/setup-buildx-action@v3

- name: Login to Docker Hub 🗝️
# if: ${{ steps.check-image-presence.outputs.not_present == '1' }}
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Pre-build dev container image 🔨
# if: ${{ steps.check-image-presence.outputs.not_present == '1' }}
uses: devcontainers/[email protected]
env:
FROM_IMAGE: ${{ steps.generate-from-parameters.outputs.from_image }}
FROM_VARIANT: ${{ steps.generate-from-parameters.outputs.from_variant }}
ANSIBLE_INSTALL_LOCATION: ${{ steps.find-ansible-install-location.outputs.ansible_install_location }}
ANSIBLE_CORE_VERSION: ${{ steps.find-ansible-core-version.outputs.ansible_core_version }}
USERNAME: ${{ inputs.username }}
UID: ${{ inputs.user_id }}
GID: ${{ inputs.group_id }}
with:
subFolder: avd-containers/${{ inputs.container_name }}
imageName: ghcr.io/${{ github.repository }}/${{ inputs.container_name }}
imageTag: ${{ steps.build-tags.outputs.image_tags }}
platform: ${{ inputs.platform }}
push: always
31 changes: 31 additions & 0 deletions .github/workflows/container_builld_universal.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
name: Build universal container

on:
push:
branches:
- devel
paths:
- avd-containers/universal/**
- .github/workflows/container_build_template.yml
- .github/workflows/container_build_universal.yml
workflow_dispatch:
branches:
- devel
release:
types: [published]

jobs:
build_universal_container:
uses: ./.github/workflows/container_build_template.yml
strategy:
matrix:
container_name: [universal]
python_version: ["3.9", "3.10", "3.11"]
include:
- python_version: "3.11"
container_tags: latest
with:
container_name: ${{ matrix.container_name }}
python_version: ${{ matrix.python_version }}
container_tags: ${{ matrix.container_tags }}
1 change: 1 addition & 0 deletions .github/workflows/pull-request-triage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ jobs:
plugins
requirements
pyavd
containers
# Configure that a scope must always be provided.
requireScope: false
# Configure additional validation for the subject based on a regex.
Expand Down
Loading

0 comments on commit b09b52a

Please sign in to comment.