Skip to content

Commit e3eb0e7

Browse files
committed
Add support for multi-arch manifest, with default arch on quay.io
(cherry picked from commit db5a75b)
1 parent 7daf106 commit e3eb0e7

File tree

1 file changed

+80
-56
lines changed

1 file changed

+80
-56
lines changed

Makefile

Lines changed: 80 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,22 @@ ifeq ($(ARCH),x86_64)
3939
override ARCH=amd64
4040
endif
4141

42+
# we want to be able to run the same recipe on multiple targets keyed on the image name
43+
# to do that, we would use the entire image name, e.g. calico/node:abcdefg, as the stem, or '%', in the target
44+
# however, make does **not** allow the usage of invalid filename characters - like / and : - in a stem, and thus errors out
45+
# to get around that, we "escape" those characters by converting all : to --- and all / to ___ , so that we can use them
46+
# in the target, we then unescape them back
47+
escapefs = $(subst :,---,$(subst /,___,$(1)))
48+
unescapefs = $(subst ---,:,$(subst ___,/,$(1)))
49+
50+
# these macros create a list of valid architectures for pushing manifests
51+
space :=
52+
space +=
53+
comma := ,
54+
prefix_linux = $(addprefix linux/,$(strip $1))
55+
join_platforms = $(subst $(space),$(comma),$(call prefix_linux,$(strip $1)))
56+
57+
4258
# Targets used when cross building.
4359
.PHONY: register
4460
# Enable binfmt adding support for miscellaneous binary formats.
@@ -55,9 +71,27 @@ VALIDARCHES = $(filter-out $(EXCLUDEARCH),$(ARCHES))
5571

5672

5773
###############################################################################
58-
CONTAINER_NAME=calico/typha
74+
BUILD_IMAGE=calico/typha
5975
PACKAGE_NAME?=github.com/projectcalico/typha
6076

77+
PUSH_IMAGES?=$(BUILD_IMAGE) quay.io/calico/typha
78+
RELEASE_IMAGES?=gcr.io/projectcalico-org/typha eu.gcr.io/projectcalico-org/typha asia.gcr.io/projectcalico-org/typha us.gcr.io/projectcalico-org/typha
79+
80+
# If this is a release, also tag and push additional images.
81+
ifeq ($(RELEASE),true)
82+
PUSH_IMAGES+=$(RELEASE_IMAGES)
83+
endif
84+
85+
# remove from the list to push to manifest any registries that do not support multi-arch
86+
EXCLUDE_MANIFEST_REGISTRIES ?= quay.io/
87+
PUSH_MANIFEST_IMAGES=$(PUSH_IMAGES:$(EXCLUDE_MANIFEST_REGISTRIES)%=)
88+
PUSH_NONMANIFEST_IMAGES=$(filter-out $(PUSH_MANIFEST_IMAGES),$(PUSH_IMAGES))
89+
90+
# location of docker credentials to push manifests
91+
DOCKER_CONFIG ?= $(HOME)/.docker/config.json
92+
93+
94+
6195
GO_BUILD_VER?=v0.17
6296
# For building, we use the go-build image for the *host* architecture, even if the target is different
6397
# the one for the host should contain all the necessary cross-compilation tools
@@ -202,8 +236,8 @@ bin/typha-client-$(ARCH): $(SRC_FILES) vendor/.up-to-date
202236
# Building the image
203237
###############################################################################
204238
# Build the calico/typha docker image, which contains only typha.
205-
.PHONY: calico/typha calico/typha-$(ARCH)
206-
image: $(CONTAINER_NAME)
239+
.PHONY: $(BUILD_IMAGE) $(BUILD_IMAGE)-$(ARCH)
240+
image: $(BUILD_IMAGE)
207241

208242
# Build the image for the target architecture
209243
.PHONY: image-all
@@ -212,14 +246,14 @@ sub-image-%:
212246
$(MAKE) image ARCH=$*
213247

214248
# Build the calico/typha docker image, which contains only Typha.
215-
.PHONY: image $(CONTAINER_NAME)
216-
$(CONTAINER_NAME): bin/calico-typha-$(ARCH) register
249+
.PHONY: image $(BUILD_IMAGE)
250+
$(BUILD_IMAGE): bin/calico-typha-$(ARCH) register
217251
rm -rf docker-image/bin
218252
mkdir -p docker-image/bin
219253
cp bin/calico-typha-$(ARCH) docker-image/bin/
220-
docker build --pull -t $(CONTAINER_NAME):latest-$(ARCH) --build-arg QEMU_IMAGE=$(CALICO_BUILD) --file ./docker-image/Dockerfile.$(ARCH) docker-image
254+
docker build --pull -t $(BUILD_IMAGE):latest-$(ARCH) --build-arg QEMU_IMAGE=$(CALICO_BUILD) --file ./docker-image/Dockerfile.$(ARCH) docker-image
221255
ifeq ($(ARCH),amd64)
222-
docker tag $(CONTAINER_NAME):latest-$(ARCH) $(CONTAINER_NAME):latest
256+
docker tag $(BUILD_IMAGE):latest-$(ARCH) $(BUILD_IMAGE):latest
223257
endif
224258

225259
# ensure we have a real imagetag
@@ -229,54 +263,44 @@ ifndef IMAGETAG
229263
endif
230264

231265
## push one arch
232-
push: imagetag
233-
docker push $(CONTAINER_NAME):$(IMAGETAG)-$(ARCH)
234-
docker push quay.io/$(CONTAINER_NAME):$(IMAGETAG)-$(ARCH)
235-
236-
# Push images to gcr.io, used by GKE.
237-
if [ "$(RELEASE)" = "true" ]; then \
238-
docker push gcr.io/projectcalico-org/typha:$(IMAGETAG)-$(ARCH) && \
239-
docker push eu.gcr.io/projectcalico-org/typha:$(IMAGETAG)-$(ARCH) && \
240-
docker push asia.gcr.io/projectcalico-org/typha:$(IMAGETAG)-$(ARCH) && \
241-
docker push us.gcr.io/projectcalico-org/typha:$(IMAGETAG)-$(ARCH); \
242-
fi;
243-
ifeq ($(ARCH),amd64)
244-
docker push $(CONTAINER_NAME):$(IMAGETAG)
245-
docker push quay.io/$(CONTAINER_NAME):$(IMAGETAG)
246-
247-
if [ "$(RELEASE)" = "true" ]; then \
248-
# Push images to gcr.io, used by GKE. Only do this for releases. \
249-
docker push gcr.io/projectcalico-org/typha:$(IMAGETAG) && \
250-
docker push eu.gcr.io/projectcalico-org/typha:$(IMAGETAG) && \
251-
docker push asia.gcr.io/projectcalico-org/typha:$(IMAGETAG) && \
252-
docker push us.gcr.io/projectcalico-org/typha:$(IMAGETAG); \
253-
fi;
254-
endif
266+
push: imagetag $(addprefix sub-single-push-,$(call escapefs,$(PUSH_IMAGES)))
267+
268+
sub-single-push-%:
269+
docker push $(call unescapefs,$*:$(IMAGETAG)-$(ARCH))
255270

256271
## push all archs
257272
push-all: imagetag $(addprefix sub-push-,$(VALIDARCHES))
258273
sub-push-%:
259274
$(MAKE) push ARCH=$* IMAGETAG=$(IMAGETAG)
260275

276+
push-manifests: imagetag $(addprefix sub-manifest-,$(call escapefs,$(PUSH_MANIFEST_IMAGES)))
277+
sub-manifest-%:
278+
# Docker login to hub.docker.com required before running this target as we are using $(DOCKER_CONFIG) holds the docker login credentials
279+
# path to credentials based on manifest-tool's requirements here https://github.com/estesp/manifest-tool#sample-usage
280+
docker run -t --entrypoint /bin/sh -v $(DOCKER_CONFIG):/root/.docker/config.json $(CALICO_BUILD) -c "/usr/bin/manifest-tool push from-args --platforms $(call join_platforms,$(VALIDARCHES)) --template $(call unescapefs,$*:$(IMAGETAG))-ARCH --target $(call unescapefs,$*:$(IMAGETAG))"
281+
282+
## push default amd64 arch where multi-arch manifest is not supported
283+
push-non-manifests: imagetag $(addprefix sub-non-manifest-,$(call escapefs,$(PUSH_NONMANIFEST_IMAGES)))
284+
sub-non-manifest-%:
285+
ifeq ($(ARCH),amd64)
286+
docker push $(call unescapefs,$*:$(IMAGETAG))
287+
else
288+
$(NOECHO) $(NOOP)
289+
endif
290+
291+
292+
261293
## tag images of one arch
262-
tag-images: imagetag
263-
docker tag $(CONTAINER_NAME):latest-$(ARCH) $(CONTAINER_NAME):$(IMAGETAG)-$(ARCH)
264-
docker tag $(CONTAINER_NAME):latest-$(ARCH) quay.io/$(CONTAINER_NAME):$(IMAGETAG)-$(ARCH)
265-
266-
# Tag images for gcr.io, used by GKE.
267-
docker tag $(CONTAINER_NAME):latest-$(ARCH) gcr.io/projectcalico-org/typha:$(IMAGETAG)-$(ARCH)
268-
docker tag $(CONTAINER_NAME):latest-$(ARCH) eu.gcr.io/projectcalico-org/typha:$(IMAGETAG)-$(ARCH)
269-
docker tag $(CONTAINER_NAME):latest-$(ARCH) asia.gcr.io/projectcalico-org/typha:$(IMAGETAG)-$(ARCH)
270-
docker tag $(CONTAINER_NAME):latest-$(ARCH) us.gcr.io/projectcalico-org/typha:$(IMAGETAG)-$(ARCH)
294+
tag-images: imagetag $(addprefix sub-single-tag-images-arch-,$(call escapefs,$(PUSH_IMAGES))) $(addprefix sub-single-tag-images-non-manifest-,$(call escapefs,$(PUSH_NONMANIFEST_IMAGES)))
295+
sub-single-tag-images-arch-%:
296+
docker tag $(BUILD_IMAGE):latest-$(ARCH) $(call unescapefs,$*:$(IMAGETAG)-$(ARCH))
297+
298+
# because some still do not support multi-arch manifest
299+
sub-single-tag-images-non-manifest-%:
271300
ifeq ($(ARCH),amd64)
272-
docker tag $(CONTAINER_NAME):latest-$(ARCH) $(CONTAINER_NAME):$(IMAGETAG)
273-
docker tag $(CONTAINER_NAME):latest-$(ARCH) quay.io/$(CONTAINER_NAME):$(IMAGETAG)
274-
275-
# Tag images for gcr.io, used by GKE.
276-
docker tag $(CONTAINER_NAME):latest-$(ARCH) gcr.io/projectcalico-org/typha:$(IMAGETAG)
277-
docker tag $(CONTAINER_NAME):latest-$(ARCH) eu.gcr.io/projectcalico-org/typha:$(IMAGETAG)
278-
docker tag $(CONTAINER_NAME):latest-$(ARCH) asia.gcr.io/projectcalico-org/typha:$(IMAGETAG)
279-
docker tag $(CONTAINER_NAME):latest-$(ARCH) us.gcr.io/projectcalico-org/typha:$(IMAGETAG)
301+
docker tag $(BUILD_IMAGE):latest-$(ARCH) $(call unescapefs,$*:$(IMAGETAG))
302+
else
303+
$(NOECHO) $(NOOP)
280304
endif
281305

282306
## tag images of all archs
@@ -349,7 +373,7 @@ endif
349373

350374
## checks that we can get the version
351375
version: image
352-
docker run --rm $(CONTAINER_NAME):latest-$(ARCH) calico-typha --version
376+
docker run --rm $(BUILD_IMAGE):latest-$(ARCH) calico-typha --version
353377

354378
## Builds the code and runs all tests.
355379
ci: image-all version static-checks ut upload-to-coveralls
@@ -366,13 +390,13 @@ endif
366390
ifndef BRANCH_NAME
367391
$(error BRANCH_NAME is undefined - run using make <target> BRANCH_NAME=var or set an environment variable)
368392
endif
369-
$(MAKE) tag-images-all push-all IMAGETAG=$(BRANCH_NAME) EXCLUDEARCH="$(EXCLUDEARCH)"
370-
$(MAKE) tag-images-all push-all IMAGETAG=$(shell git describe --tags --dirty --always --long) EXCLUDEARCH="$(EXCLUDEARCH)"
393+
$(MAKE) tag-images-all push-all push-manifests push-non-manifests IMAGETAG=$(BRANCH_NAME) EXCLUDEARCH="$(EXCLUDEARCH)"
394+
$(MAKE) tag-images-all push-all push-manifests push-non-manifests IMAGETAG=$(shell git describe --tags --dirty --always --long) EXCLUDEARCH="$(EXCLUDEARCH)"
371395

372396
k8sfv-test: image
373397
cd .. && git clone https://github.com/projectcalico/felix.git && cd felix; \
374398
[ ! -e ../typha/semaphore-felix-branch ] || git checkout $(cat ../typha/semaphore-felix-branch); \
375-
JUST_A_MINUTE=true USE_TYPHA=true FV_TYPHAIMAGE=calico/typha:latest TYPHA_VERSION=latest $(MAKE) k8sfv-test
399+
JUST_A_MINUTE=true USE_TYPHA=true FV_TYPHAIMAGE=$(BUILD_IMAGE):latest TYPHA_VERSION=latest $(MAKE) k8sfv-test
376400

377401

378402
###############################################################################
@@ -415,8 +439,8 @@ endif
415439
## Verifies the release artifacts produces by `make release-build` are correct.
416440
release-verify: release-prereqs
417441
# Check the reported version is correct for each release artifact.
418-
docker run --rm $(CONTAINER_NAME):$(VERSION)-$(ARCH) calico-typha --version | grep $(VERSION) || ( echo "Reported version:" `docker run --rm $(CONTAINER_NAME):$(VERSION)-$(ARCH) calico-typha --version` "\nExpected version: $(VERSION)" && exit 1 )
419-
docker run --rm quay.io/$(CONTAINER_NAME):$(VERSION)-$(ARCH) calico-typha --version | grep $(VERSION) || ( echo "Reported version:" `docker run --rm quay.io/$(CONTAINER_NAME):$(VERSION)-$(ARCH) calico-typha --version | grep -x $(VERSION)` "\nExpected version: $(VERSION)" && exit 1 )
442+
docker run --rm $(BUILD_IMAGE):$(VERSION)-$(ARCH) calico-typha --version | grep $(VERSION) || ( echo "Reported version:" `docker run --rm $(BUILD_IMAGE):$(VERSION)-$(ARCH) calico-typha --version` "\nExpected version: $(VERSION)" && exit 1 )
443+
docker run --rm quay.io/$(BUILD_IMAGE):$(VERSION)-$(ARCH) calico-typha --version | grep $(VERSION) || ( echo "Reported version:" `docker run --rm quay.io/$(BUILD_IMAGE):$(VERSION)-$(ARCH) calico-typha --version | grep -x $(VERSION)` "\nExpected version: $(VERSION)" && exit 1 )
420444

421445
# TODO: Some sort of quick validation of the produced binaries.
422446

@@ -450,8 +474,8 @@ release-publish: release-prereqs
450474
## Pushes `latest` release images. WARNING: Only run this for latest stable releases.
451475
release-publish-latest: release-prereqs
452476
# Check latest versions match.
453-
if ! docker run $(CONTAINER_NAME):latest-$(ARCH) calico-typha --version | grep '$(VERSION)'; then echo "Reported version:" `docker run $(CONTAINER_NAME):latest-$(ARCH) calico-typha --version` "\nExpected version: $(VERSION)"; false; else echo "\nVersion check passed\n"; fi
454-
if ! docker run quay.io/$(CONTAINER_NAME):latest-$(ARCH) calico-typha --version | grep '$(VERSION)'; then echo "Reported version:" `docker run quay.io/$(CONTAINER_NAME):latest-$(ARCH) calico-typha --version` "\nExpected version: $(VERSION)"; false; else echo "\nVersion check passed\n"; fi
477+
if ! docker run $(BUILD_IMAGE):latest-$(ARCH) calico-typha --version | grep '$(VERSION)'; then echo "Reported version:" `docker run $(BUILD_IMAGE):latest-$(ARCH) calico-typha --version` "\nExpected version: $(VERSION)"; false; else echo "\nVersion check passed\n"; fi
478+
if ! docker run quay.io/$(BUILD_IMAGE):latest-$(ARCH) calico-typha --version | grep '$(VERSION)'; then echo "Reported version:" `docker run quay.io/$(BUILD_IMAGE):latest-$(ARCH) calico-typha --version` "\nExpected version: $(VERSION)"; false; else echo "\nVersion check passed\n"; fi
455479

456480
$(MAKE) push RELEASE=true IMAGETAG=latest ARCH=$(ARCH)
457481

@@ -527,7 +551,7 @@ help:
527551
@echo "Builds:"
528552
@echo
529553
@echo " make all Build all the binary packages."
530-
@echo " make image Build $(CONTAINER_NAME) docker image."
554+
@echo " make image Build $(BUILD_IMAGE) docker image."
531555
@echo
532556
@echo "Tests:"
533557
@echo

0 commit comments

Comments
 (0)