jenkins/raspberrypi/pyscripts/build_docker_image.py (160 lines of code) (raw):
# Copyright (c) Microsoft. All rights reserved.
# Licensed under the MIT license. See LICENSE file in the project root for full license information
import os
import docker
import json
import sys
import docker_tags
import argparse
import datetime
import colorama
from colorama import Fore
colorama.init(autoreset=True)
default_repo = "(Azure/azure-iot-sdk-BLAH)"
parser = argparse.ArgumentParser(description="build docker image for testing")
parser.add_argument("--repo", help="repo with source", type=str, default=default_repo)
parser.add_argument(
"--commit", help="commit to apply (ref or branch)", type=str, default="main"
)
args = parser.parse_args()
if args.repo == default_repo:
args.repo = "Azure/azure-iot-sdk-c"
print(Fore.YELLOW + "Repo not specified. Defaulting to " + args.repo)
print_separator = "".join("/\\" for _ in range(80))
auth_config = {
"username": os.environ["AZURECR_REPO_USER"],
"password": os.environ["AZURECR_REPO_PASSWORD"],
}
def print_filtered_docker_line(line):
try:
obj = json.loads(line.decode("utf-8"))
except:
print(line)
else:
if "status" in obj:
if "id" in obj:
if obj["status"] not in [
"Waiting",
"Downloading",
"Verifying Checksum",
"Extracting",
"Preparing",
"Pushing",
]:
print("{}: {}".format(obj["status"], obj["id"]))
else:
pass
else:
print(obj["status"])
elif "error" in obj:
raise Exception(obj["error"])
else:
print(line)
def build_image(tags):
print(print_separator)
print("BUILDING IMAGE")
print(print_separator)
dockerfile = "Dockerfile"
dockerfile_directory = os.path.normpath(os.path.join(os.path.dirname(os.path.realpath(__file__)), "../"))
api_client = docker.APIClient(base_url="unix://var/run/docker.sock")
build_args = {
"CLIENTLIBRARY_REPO": tags.repo,
"CLIENTLIBRARY_COMMIT_NAME": tags.commit_name,
"CLIENTLIBRARY_COMMIT_SHA": tags.commit_sha
}
if tags.image_tag_to_use_for_cache:
cache_from = [
tags.docker_full_image_name + ":" + tags.image_tag_to_use_for_cache
]
print("using {} for cache".format(cache_from[0]))
else:
cache_from = []
print(
Fore.YELLOW
+ "Building image for "
+ tags.docker_image_name
+ " using "
+ dockerfile
)
for line in api_client.build(
path=dockerfile_directory,
tag=tags.docker_image_name,
buildargs=build_args,
cache_from=cache_from,
dockerfile=dockerfile,
):
try:
sys.stdout.write(json.loads(line.decode("utf-8"))["stream"])
except KeyError:
print_filtered_docker_line(line)
def tag_images(tags):
print(print_separator)
print("TAGGING IMAGE")
print(print_separator)
api_client = docker.APIClient(base_url="unix://var/run/docker.sock")
print("Adding tags")
for image_tag in tags.image_tags:
print("Adding " + image_tag)
api_client.tag(tags.docker_image_name, tags.docker_full_image_name, image_tag)
def push_images(tags):
print(print_separator)
print("PUSHING IMAGE")
print(print_separator)
api_client = docker.APIClient(base_url="unix://var/run/docker.sock")
for image_tag in tags.image_tags:
print("Pushing {}:{}".format(tags.docker_full_image_name, image_tag))
for line in api_client.push(
tags.docker_full_image_name, image_tag, stream=True, auth_config=auth_config
):
print_filtered_docker_line(line)
def extract_artifacts(tags):
print(print_separator)
print("GETTING CMAKE AS ARCHIVE")
print(print_separator)
# Publish directory should be in the top level folder of the sdk.
source_artifacts = os.path.normpath(os.path.join(os.path.dirname(os.path.realpath(__file__)), "../../source_artifacts.tar"))
api_client = docker.APIClient(base_url="unix://var/run/docker.sock")
for image in api_client.images():
print("Image:")
print(image)
print("Creating Container: {}".format(tags.docker_image_name))
con = api_client.create_container(tags.docker_image_name)
print(con)
bits, stat = api_client.get_archive(con["Id"],"/sdk/cmake")
print(stat)
with open(source_artifacts, 'wb') as f:
for chunk in bits:
f.write(chunk)
def prefetch_cached_images(tags):
if docker_tags.running_on_azure_pipelines():
print(print_separator)
print(Fore.YELLOW + "PREFETCHING IMAGE")
print(print_separator)
tags.image_tag_to_use_for_cache = None
api_client = docker.APIClient(base_url="unix://var/run/docker.sock")
for image_tag in tags.image_tags:
print(
Fore.YELLOW
+ "trying to prefetch {}:{}".format(
tags.docker_full_image_name, image_tag
)
)
try:
for line in api_client.pull(
tags.docker_full_image_name,
image_tag,
stream=True,
auth_config=auth_config,
):
print_filtered_docker_line(line)
tags.image_tag_to_use_for_cache = image_tag
print(
Fore.GREEN
+ "Found {}. Using this for image cache".format(image_tag)
)
return
except docker.errors.APIError:
print(Fore.YELLOW + "Image not found in repository")
tags = docker_tags.get_docker_tags_from_commit(args.repo, args.commit)
prefetch_cached_images(tags)
build_image(tags)
tag_images(tags)
push_images(tags)
extract_artifacts(tags)