├── Jenkinsfile_k8s ├── updatecli ├── values.yaml └── updatecli.d │ ├── get-fileshare-signed-url.yaml │ ├── geoipupdate.yaml │ ├── azcopy.yaml │ └── azure-cli.yaml ├── README.adoc ├── Jenkinsfile_updatecli ├── LICENSE ├── cst.yaml ├── get-fileshare-signed-url.sh └── Dockerfile /Jenkinsfile_k8s: -------------------------------------------------------------------------------- 1 | buildDockerAndPublishImage('infratools', [ 2 | targetplatforms: 'linux/amd64,linux/arm64', 3 | ]) 4 | -------------------------------------------------------------------------------- /updatecli/values.yaml: -------------------------------------------------------------------------------- 1 | github: 2 | user: "Jenkins Infra Bot (updatecli)" 3 | email: "60776566+jenkins-infra-bot@users.noreply.github.com" 4 | token: "UPDATECLI_GITHUB_TOKEN" 5 | branch: "main" 6 | owner: "jenkins-infra" 7 | repository: "docker-infratools" 8 | -------------------------------------------------------------------------------- /README.adoc: -------------------------------------------------------------------------------- 1 | = Docker Image for Jenkins Infra tasks 2 | 3 | This repository hosts the resources to build a Docker Image used for multiple task on the jenkins infra (gc dockerhub mirror, geoip) 4 | 5 | == Contribute 6 | 7 | If you want to contribute, or build/test the Docker Image, please refer to the following documentation about Docker images for the Jenkins Infra project: 8 | link:https://github.com/jenkins-infra/pipeline-library/blob/master/resources/io/jenkins/infra/docker/README.adoc[README] 9 | -------------------------------------------------------------------------------- /Jenkinsfile_updatecli: -------------------------------------------------------------------------------- 1 | final String cronExpr = env.BRANCH_IS_PRIMARY ? '@daily' : '' 2 | 3 | properties([ 4 | buildDiscarder(logRotator(numToKeepStr: '10')), 5 | disableConcurrentBuilds(abortPrevious: true), 6 | pipelineTriggers([cron(cronExpr)]), 7 | ]) 8 | 9 | timeout(time: 10, unit: 'MINUTES') { 10 | final String updatecliAction = env.BRANCH_IS_PRIMARY ? 'apply' : 'diff' 11 | stage("Run updatecli action: ${updatecliAction}") { 12 | updatecli( 13 | action: updatecliAction, 14 | ) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Jenkins Infra 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /updatecli/updatecli.d/get-fileshare-signed-url.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Keep `get-fileshare-signed-url.sh` up to date 3 | 4 | scms: 5 | default: 6 | kind: github 7 | spec: 8 | user: "{{ .github.user }}" 9 | email: "{{ .github.email }}" 10 | owner: "{{ .github.owner }}" 11 | repository: "{{ .github.repository }}" 12 | token: "{{ requiredEnv .github.token }}" 13 | username: "{{ .github.username }}" 14 | branch: "{{ .github.branch }}" 15 | 16 | sources: 17 | latestVersion: 18 | name: Get latest get-fileshare-signed-url.sh version 19 | kind: file 20 | spec: 21 | file: https://raw.githubusercontent.com/jenkins-infra/pipeline-library/refs/heads/master/resources/get-fileshare-signed-url.sh 22 | 23 | targets: 24 | update-get-fileshare-signed-url: 25 | name: Update `get-fileshare-signed-url.sh` file 26 | sourceid: latestVersion 27 | kind: file 28 | spec: 29 | file: ./get-fileshare-signed-url.sh 30 | scmid: default 31 | 32 | actions: 33 | default: 34 | kind: github/pullrequest 35 | scmid: default 36 | title: Update `get-fileshare-signed-url.sh` file 37 | spec: 38 | labels: 39 | - dependencies 40 | -------------------------------------------------------------------------------- /cst.yaml: -------------------------------------------------------------------------------- 1 | schemaVersion: 2.0.0 2 | metadataTest: 3 | entrypoint: ["/usr/bin/entrypoint.sh"] 4 | user: azcopy 5 | fileExistenceTests: 6 | - name: "azcopy" 7 | path: "/usr/bin/azcopy" 8 | shouldExist: true 9 | isExecutableBy: "any" 10 | uid: 1000 11 | gid: 1000 12 | - name: "az" 13 | path: "/usr/bin/az" 14 | shouldExist: true 15 | isExecutableBy: "any" 16 | uid: 0 17 | gid: 0 18 | - name: "geoipupdate" 19 | path: "/usr/bin/geoipupdate" 20 | shouldExist: true 21 | isExecutableBy: "any" 22 | uid: 1000 23 | gid: 1000 24 | - name: "Entrypoint script" 25 | path: "/usr/bin/entrypoint.sh" 26 | shouldExist: true 27 | isExecutableBy: "any" 28 | uid: 0 29 | gid: 0 30 | - name: "get-fileshare-signed-url.sh" 31 | path: "/usr/bin/get-fileshare-signed-url.sh" 32 | shouldExist: true 33 | isExecutableBy: "any" 34 | uid: 0 35 | gid: 0 36 | commandTests: 37 | - name: "Check azcopy Version" 38 | command: "azcopy" 39 | args: ["--version"] 40 | expectedOutput: ["\"azcopy version 10.29.1\""] 41 | - name: "Check geoipupdate Version" 42 | command: "geoipupdate" 43 | args: ["--version"] 44 | expectedError: ["\"geoipupdate 7.1.1\""] 45 | - name: "Check az Version" 46 | command: "az" 47 | args: ["--version"] 48 | expectedOutput: ["\"azure-cli 2.75.0\""] 49 | -------------------------------------------------------------------------------- /updatecli/updatecli.d/geoipupdate.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bump `Geoipupdate`version` 3 | 4 | scms: 5 | default: 6 | kind: github 7 | spec: 8 | user: "{{ .github.user }}" 9 | email: "{{ .github.email }}" 10 | owner: "{{ .github.owner }}" 11 | repository: "{{ .github.repository }}" 12 | token: "{{ requiredEnv .github.token }}" 13 | username: "{{ .github.username }}" 14 | branch: "{{ .github.branch }}" 15 | 16 | sources: 17 | latestVersion: 18 | name: Get latest geoipupdater version 19 | kind: githubrelease 20 | spec: 21 | owner: "maxmind" 22 | repository: "geoipupdate" 23 | token: "{{ requiredEnv .github.token }}" 24 | username: "{{ .github.username }}" 25 | 26 | targets: 27 | updateDockerfileVersion: 28 | name: Update the value of ARG GEOIPUPDATE_VERSION in the Dockerfile 29 | sourceid: latestVersion 30 | kind: dockerfile 31 | spec: 32 | file: ./Dockerfile 33 | instruction: 34 | keyword: ARG 35 | matcher: GEOIPUPDATE_VERSION 36 | scmid: default 37 | updateCstVersion: 38 | name: Update test harness with new `geoipupdater`` version 39 | sourceid: latestVersion 40 | kind: yaml 41 | spec: 42 | file: ./cst.yaml 43 | key: $.commandTests[1].expectedError[0] 44 | transformers: 45 | - trimprefix: 'v' 46 | - addprefix: '"geoipupdate ' 47 | - addsuffix: '"' 48 | scmid: default 49 | 50 | actions: 51 | default: 52 | kind: github/pullrequest 53 | scmid: default 54 | title: Bump `Geoipupdate` version to {{ source "latestVersion" }} 55 | spec: 56 | labels: 57 | - dependencies 58 | -------------------------------------------------------------------------------- /updatecli/updatecli.d/azcopy.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bump `azcopy` version 3 | 4 | scms: 5 | default: 6 | kind: github 7 | spec: 8 | user: "{{ .github.user }}" 9 | email: "{{ .github.email }}" 10 | owner: "{{ .github.owner }}" 11 | repository: "{{ .github.repository }}" 12 | token: "{{ requiredEnv .github.token }}" 13 | username: "{{ .github.username }}" 14 | branch: "{{ .github.branch }}" 15 | 16 | sources: 17 | latestVersion: 18 | kind: githubrelease 19 | name: Get the latest `azcopy` version 20 | spec: 21 | owner: Azure 22 | repository: azure-storage-azcopy 23 | token: "{{ requiredEnv .github.token }}" 24 | username: "{{ .github.username }}" 25 | versionFilter: 26 | kind: semver 27 | transformers: 28 | - trimprefix: 'v' 29 | 30 | targets: 31 | updateDockerfileVersion: 32 | name: Update the value of ARG AZCOPY_VERSION in the Dockerfile 33 | sourceid: latestVersion 34 | kind: dockerfile 35 | spec: 36 | file: ./Dockerfile 37 | instruction: 38 | keyword: ARG 39 | matcher: AZCOPY_VERSION 40 | scmid: default 41 | updateCstVersion: 42 | name: Update test harness with new `azcopy` version 43 | sourceid: latestVersion 44 | kind: yaml 45 | spec: 46 | file: ./cst.yaml 47 | key: $.commandTests[0].expectedOutput[0] 48 | transformers: 49 | - addprefix: '"azcopy version ' 50 | - addsuffix: '"' 51 | scmid: default 52 | 53 | actions: 54 | default: 55 | kind: github/pullrequest 56 | scmid: default 57 | title: Bump `azcopy` version to {{ source "latestVersion" }} 58 | spec: 59 | labels: 60 | - dependencies 61 | -------------------------------------------------------------------------------- /updatecli/updatecli.d/azure-cli.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bump `azure-cli` version 3 | 4 | scms: 5 | default: 6 | kind: github 7 | spec: 8 | user: "{{ .github.user }}" 9 | email: "{{ .github.email }}" 10 | owner: "{{ .github.owner }}" 11 | repository: "{{ .github.repository }}" 12 | token: "{{ requiredEnv .github.token }}" 13 | username: "{{ .github.username }}" 14 | branch: "{{ .github.branch }}" 15 | 16 | sources: 17 | latestVersion: 18 | kind: githubrelease 19 | name: Get the latest `azure-cli` version 20 | spec: 21 | owner: "Azure" 22 | repository: "azure-cli" 23 | token: "{{ requiredEnv .github.token }}" 24 | username: "{{ .github.username }}" 25 | typefilter: 26 | latest: true 27 | transformers: 28 | - trimprefix: 'azure-cli-' 29 | 30 | targets: 31 | updateDockerfileVersion: 32 | name: Update the value of ARG AZ_VERSION in the Dockerfile 33 | sourceid: latestVersion 34 | kind: dockerfile 35 | spec: 36 | file: ./Dockerfile 37 | instruction: 38 | keyword: ARG 39 | matcher: AZ_VERSION 40 | scmid: default 41 | updateCstVersion: 42 | name: Update test harness with new `az` version 43 | sourceid: latestVersion 44 | kind: yaml 45 | spec: 46 | file: ./cst.yaml 47 | key: $.commandTests[2].expectedOutput[0] 48 | transformers: 49 | - addprefix: '"azure-cli ' 50 | - addsuffix: '"' 51 | scmid: default 52 | 53 | actions: 54 | default: 55 | kind: github/pullrequest 56 | title: Bump `azure-cli` version to {{ source "latestVersion" }} 57 | scmid: default 58 | spec: 59 | labels: 60 | - enhancement 61 | - azure-cli 62 | -------------------------------------------------------------------------------- /get-fileshare-signed-url.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Purpose: Shell script to get a file share URL signed with a short-lived SAS token 3 | # -- 4 | # Description: This script uses either a service principal or either a storage account access key to generate a SAS token 5 | # and returns the file share URL composed of the storage resource URI and the SAS token. 6 | # Ref: https://learn.microsoft.com/en-us/azure/storage/common/storage-sas-overview 7 | # -- 8 | # Usage: 9 | # - Return a file share signed URL: ./get-fileshare-signed-url.sh 10 | # - Interact with a file share and azcopy: azcopy list "$(./get-fileshare-signed-url.sh)" 11 | # -- 12 | # Required parameters defined as environment variables: 13 | # - STORAGE_FILESHARE: the file share name 14 | # - STORAGE_NAME: the storage account name where the file share is located 15 | # - STORAGE_DURATION_IN_MINUTE: lifetime of the short-lived SAS token, in minute 16 | # - STORAGE_PERMISSIONS: the permission(s) granted on the file share, any of "dlrw" (note: the order matters) 17 | # 18 | # Depending on wether you want to use a service principal or an access key to generate the SAS token, you'll also need either: 19 | # - AZURE_STORAGE_KEY: the storage account access key 20 | # or 21 | # - JENKINS_INFRA_FILESHARE_CLIENT_ID: the service principal app registration client id 22 | # - JENKINS_INFRA_FILESHARE_CLIENT_SECRET: the service principal client secret 23 | # - JENKINS_INFRA_FILESHARE_TENANT_ID: the file share tenant id 24 | # -------------------------------------------------------------------------------- 25 | set -Eeu -o pipefail 26 | 27 | # Don't print any trace 28 | set +x 29 | 30 | : "${STORAGE_FILESHARE?}" "${STORAGE_NAME?}" "${STORAGE_DURATION_IN_MINUTE?}" "${STORAGE_PERMISSIONS?}" 31 | 32 | # Ensure the script is re-entrant by using unique temporary `az` configuration directory for each call 33 | # Ref. https://learn.microsoft.com/en-us/cli/azure/use-azure-cli-successfully?tabs=bash%2Cbash2#concurrent-execution 34 | AZURE_CONFIG_DIR="$(mktemp -d)" 35 | export AZURE_CONFIG_DIR 36 | 37 | accountKeyArg=() 38 | shouldLogout="true" 39 | # If a storage account key env var exists, use it instead of a service principal to generate a file share SAS token 40 | if [[ -n "${AZURE_STORAGE_KEY:=""}" ]]; then 41 | accountKeyArg=("--account-key" "${AZURE_STORAGE_KEY}") 42 | shouldLogout="false" 43 | else 44 | # If there is no account key env var defined, require env vars needed to use a service principal 45 | : "${JENKINS_INFRA_FILESHARE_CLIENT_ID?}" "${JENKINS_INFRA_FILESHARE_CLIENT_SECRET?}" "${JENKINS_INFRA_FILESHARE_TENANT_ID?}" 46 | 47 | # Login without the JSON output from az 48 | az login --service-principal \ 49 | --user "${JENKINS_INFRA_FILESHARE_CLIENT_ID}" \ 50 | --password "${JENKINS_INFRA_FILESHARE_CLIENT_SECRET}" \ 51 | --tenant "${JENKINS_INFRA_FILESHARE_TENANT_ID}" > /dev/null 52 | fi 53 | 54 | # date(1) isn't GNU compliant on MacOS, using gdate(1) in that case 55 | [[ "$(uname || true)" == "Darwin" ]] && dateCmd="gdate" || dateCmd="date" 56 | expiry="$("${dateCmd}" --utc --date "+ ${STORAGE_DURATION_IN_MINUTE} minutes" +"%Y-%m-%dT%H:%MZ")" 57 | 58 | # Generate a SAS token, remove double quotes around it and replace potential '/' by '%2F' 59 | token="$(az storage share generate-sas "${accountKeyArg[@]}" \ 60 | --name "${STORAGE_FILESHARE}" \ 61 | --account-name "${STORAGE_NAME}" \ 62 | --https-only \ 63 | --permissions "${STORAGE_PERMISSIONS}" \ 64 | --expiry "${expiry}" \ 65 | --only-show-errors \ 66 | | sed 's/\"//g' \ 67 | | sed 's|/|%2F|g')" 68 | 69 | [[ "${shouldLogout}" == "true" ]] && az logout 70 | 71 | echo "https://${STORAGE_NAME}.file.core.windows.net/${STORAGE_FILESHARE}/?${token}" 72 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | ARG GEOIPUPDATE_VERSION=v7.1.1 2 | ARG AZCOPY_VERSION=10.29.1 3 | ARG AZ_VERSION=2.75.0 4 | ARG KUBECTL_VERSION=1.26.12 5 | 6 | FROM ubuntu:22.04 7 | 8 | SHELL ["/bin/bash", "-o", "pipefail", "-c"] 9 | 10 | # hadolint ignore=DL3008 11 | RUN apt-get update && apt-get install -y --no-install-recommends jq wget ca-certificates gnupg lsb-release\ 12 | && apt-get clean \ 13 | && rm -rf /var/lib/apt/lists/* 14 | 15 | ARG user=azcopy 16 | ARG group=azcopy 17 | ARG uid=1000 18 | ARG gid=1000 19 | ARG user_home="/home/${user}" 20 | RUN groupadd -g ${gid} ${group} \ 21 | && useradd -l -d "${user_home}" -u "${uid}" -g "${gid}" -m -s /bin/bash "${user}" 22 | 23 | ARG AZCOPY_VERSION=10.29.1 24 | RUN rep_config_pkg="$(mktemp)" \ 25 | # Download and install the repository configuration package. 26 | && wget -qO- "https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb" -O "${rep_config_pkg}" \ 27 | && dpkg --install "${rep_config_pkg}" \ 28 | && rm -f "${rep_config_pkg}" \ 29 | && apt-get update --quiet \ 30 | && apt-get install --yes --no-install-recommends azcopy="${AZCOPY_VERSION}" \ 31 | # Sanity check 32 | && azcopy --version \ 33 | # Cleanup 34 | && apt-get clean \ 35 | && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 36 | 37 | ARG AZ_VERSION=2.75.0 38 | RUN mkdir -p /etc/apt/keyrings && \ 39 | wget --quiet --output-document - "https://packages.microsoft.com/keys/microsoft.asc" | gpg --dearmor | tee /etc/apt/keyrings/microsoft.gpg > /dev/null && \ 40 | chmod go+r /etc/apt/keyrings/microsoft.gpg && \ 41 | AZ_DIST="$(lsb_release -cs)" && \ 42 | printf 'Types: deb\nURIs: https://packages.microsoft.com/repos/azure-cli/\nSuites: %s\nComponents: main\nArchitectures: %s\nSigned-by: /etc/apt/keyrings/microsoft.gpg' "${AZ_DIST}" "$(dpkg --print-architecture)" | tee /etc/apt/sources.list.d/azure-cli.sources && \ 43 | apt-get update && apt-get install -y --no-install-recommends azure-cli="${AZ_VERSION}-1~${AZ_DIST}" && apt-get clean && rm -rf /var/lib/apt/lists/* 44 | 45 | ARG GEOIPUPDATE_VERSION=v7.1.1 46 | RUN ARCH="$(uname -m)" && \ 47 | if [ "$ARCH" = "x86_64" ]; then \ 48 | DOWNLOAD_URL="https://github.com/maxmind/geoipupdate/releases/download/${GEOIPUPDATE_VERSION}/geoipupdate_${GEOIPUPDATE_VERSION#v}_linux_amd64.tar.gz"; \ 49 | elif [ "$ARCH" = "aarch64" ]; then \ 50 | DOWNLOAD_URL="https://github.com/maxmind/geoipupdate/releases/download/${GEOIPUPDATE_VERSION}/geoipupdate_${GEOIPUPDATE_VERSION#v}_linux_arm64.tar.gz"; \ 51 | else \ 52 | echo "Unsupported architecture: $ARCH" && exit 1; \ 53 | fi \ 54 | && wget -qO- "${DOWNLOAD_URL}" -O /tmp/geoipupdate.tgz \ 55 | && BIN_LOCATION=$(tar -tzf /tmp/geoipupdate.tgz | grep "/geoipupdate$") \ 56 | && export BIN_LOCATION \ 57 | && tar -xvzf /tmp/geoipupdate.tgz --strip-components=1 --directory=/usr/bin/ "$BIN_LOCATION" \ 58 | && chmod +x /usr/bin/geoipupdate 59 | 60 | ARG KUBECTL_VERSION 61 | RUN ARCH="$(uname -m)" && \ 62 | if [ "$ARCH" = "x86_64" ]; then \ 63 | DOWNLOAD_URL="https://storage.googleapis.com/kubernetes-release/release/v${KUBECTL_VERSION}/bin/linux/amd64/kubectl"; \ 64 | elif [ "$ARCH" = "aarch64" ]; then \ 65 | DOWNLOAD_URL="https://storage.googleapis.com/kubernetes-release/release/v${KUBECTL_VERSION}/bin/linux/arm64/kubectl"; \ 66 | else \ 67 | echo "Unsupported architecture: $ARCH" && exit 1; \ 68 | fi \ 69 | && wget "${DOWNLOAD_URL}" --quiet --output-document=/usr/local/bin/kubectl \ 70 | && chmod +x /usr/local/bin/kubectl \ 71 | && kubectl version --client --output=yaml 2>&1 | grep -q "${KUBECTL_VERSION}" 72 | 73 | USER "${user}" 74 | 75 | COPY get-fileshare-signed-url.sh /usr/bin/get-fileshare-signed-url.sh 76 | --------------------------------------------------------------------------------