Add a Helm chart collator
This adds a Dockerfile for an image which works as a Helm chart repository. Charts can be pulled from either pre-existing Helm repos or from git repos. Change-Id: I860394eea3c322f2b142ea00dd7cc0a6916c34d5
This commit is contained in:
parent
6a98b4cc7e
commit
116eb2cc93
36
helm-chart-collator/Dockerfile
Normal file
36
helm-chart-collator/Dockerfile
Normal file
@ -0,0 +1,36 @@
|
||||
FROM ubuntu:20.04 as chart-collator
|
||||
|
||||
SHELL ["bash", "-exc"]
|
||||
ENV DEBIAN_FRONTEND noninteractive
|
||||
|
||||
# Update distro and install ansible and git
|
||||
RUN apt-get update && \
|
||||
apt-get dist-upgrade -y && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
python3-minimal \
|
||||
python3-pip \
|
||||
python3-apt \
|
||||
python3-setuptools \
|
||||
openssh-client \
|
||||
jq \
|
||||
git && \
|
||||
pip3 install --upgrade wheel && \
|
||||
pip3 install --upgrade ansible && \
|
||||
pip3 install --upgrade jmespath && \
|
||||
pip3 install --upgrade yq && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY playbooks /opt/playbooks
|
||||
|
||||
ARG CHARTS=""
|
||||
RUN ansible-playbook -v /opt/playbooks/create_repository.yaml \
|
||||
-i /opt/playbooks/inventory.yaml \
|
||||
--extra-vars "CHARTS=$CHARTS"
|
||||
|
||||
FROM chartmuseum/chartmuseum:latest
|
||||
|
||||
COPY --from=chart-collator /charts /charts
|
||||
|
||||
ENTRYPOINT /chartmuseum --debug --port=8080 \
|
||||
--storage="local" \
|
||||
--storage-local-rootdir=/charts
|
134
helm-chart-collator/Makefile
Normal file
134
helm-chart-collator/Makefile
Normal file
@ -0,0 +1,134 @@
|
||||
# Copyright 2018 AT&T Intellectual Property. All other rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
SHELL := /bin/bash
|
||||
BUILD_DIR ?= build
|
||||
PUSH_IMAGE ?= false
|
||||
IMAGE_ID ?= none
|
||||
COMMIT ?= $(shell git rev-parse HEAD)
|
||||
LABEL ?= org.airshipit.build=community
|
||||
IMAGE_NAME ?= collator
|
||||
DOCKER_REGISTRY ?= quay.io
|
||||
IMAGE_PREFIX ?= airshipit
|
||||
IMAGE_TAG ?= latest
|
||||
DISTRO ?= debian_stable
|
||||
IMAGE := ${DOCKER_REGISTRY}/${IMAGE_PREFIX}/${IMAGE_NAME}:${IMAGE_TAG}-${DISTRO}
|
||||
SH_TO_CHECK := $(wildcard files/*.sh )
|
||||
PROXY ?= http://proxy.foo.com:8000
|
||||
NO_PROXY ?= localhost,127.0.0.1,.svc.cluster.local
|
||||
USE_PROXY ?= false
|
||||
|
||||
all: lint images
|
||||
|
||||
check-docker:
|
||||
@if [ -z $$(which docker) ]; then \
|
||||
echo "Missing \`docker\` client which is required for development"; \
|
||||
exit 2; \
|
||||
fi
|
||||
|
||||
images: check-docker build_collator
|
||||
|
||||
docs: clean build_docs
|
||||
|
||||
build_docs:
|
||||
echo TODO
|
||||
|
||||
run_images: run_collator
|
||||
|
||||
run_collator: $(BUILD_DIR)/output-metadata.yaml
|
||||
echo OK
|
||||
#TODO consistance test
|
||||
|
||||
$(BUILD_DIR)/output-metadata.yaml: $(BUILD_DIR)/image_id
|
||||
ifeq ($(USE_PROXY), true)
|
||||
docker run --rm -it -p 8080:8080 tester
|
||||
docker run \
|
||||
--rm \
|
||||
-e http_proxy=$(PROXY) \
|
||||
-e https_proxy=$(PROXY) \
|
||||
-e HTTP_PROXY=$(PROXY) \
|
||||
-e HTTPS_PROXY=$(PROXY) \
|
||||
-e no_proxy=$(NO_PROXY) \
|
||||
-e NO_PROXY=$(NO_PROXY) \
|
||||
$(shell cat $(BUILD_DIR)/image_id)
|
||||
else
|
||||
docker run \
|
||||
--rm \
|
||||
$(shell cat $(BUILD_DIR)/image_id)
|
||||
endif
|
||||
|
||||
$(BUILD_DIR)/image_id: build_collator
|
||||
|
||||
build_collator:
|
||||
mkdir -p $(BUILD_DIR)
|
||||
ifeq ($(IMAGE_ID), none)
|
||||
ifeq ($(USE_PROXY), true)
|
||||
docker build . \
|
||||
--tag $(IMAGE) \
|
||||
--label $(LABEL) \
|
||||
--label "org.opencontainers.image.revision=$(COMMIT)" \
|
||||
--label "org.opencontainers.image.created=\
|
||||
$(shell date --rfc-3339=seconds --utc)" \
|
||||
--label "org.opencontainers.image.title=$(IMAGE_NAME)" \
|
||||
--build-arg http_proxy=$(PROXY) \
|
||||
--build-arg https_proxy=$(PROXY) \
|
||||
--build-arg HTTP_PROXY=$(PROXY) \
|
||||
--build-arg HTTPS_PROXY=$(PROXY) \
|
||||
--build-arg no_proxy=$(NO_PROXY) \
|
||||
--build-arg NO_PROXY=$(NO_PROXY) \
|
||||
--build-arg GIT_COMMIT=$(COMMIT)
|
||||
else
|
||||
docker build . \
|
||||
--tag $(IMAGE) \
|
||||
--label $(LABEL) \
|
||||
--label "org.opencontainers.image.revision=$(COMMIT)" \
|
||||
--label "org.opencontainers.image.created=\
|
||||
$(shell date --rfc-3339=seconds --utc)" \
|
||||
--label "org.opencontainers.image.title=$(IMAGE_NAME)" \
|
||||
--build-arg GIT_COMMIT=$(COMMIT)
|
||||
endif
|
||||
echo $(shell docker images -q $(IMAGE)) > $(BUILD_DIR)/image_id
|
||||
else
|
||||
echo $(IMAGE_ID) > $(BUILD_DIR)/image_id
|
||||
endif
|
||||
ifeq ($(PUSH_IMAGE), true)
|
||||
docker push $(IMAGE)
|
||||
endif
|
||||
|
||||
clean:
|
||||
ifeq ($(IMAGE_ID), none)
|
||||
if [[ -s $(BUILD_DIR)/image_id ]]; \
|
||||
then \
|
||||
docker rmi $$(cat $(BUILD_DIR)/image_id); \
|
||||
fi
|
||||
endif
|
||||
rm -rf $(BUILD_DIR)
|
||||
|
||||
# style checks
|
||||
lint: test-shellcheck
|
||||
echo "TODO"
|
||||
|
||||
tests: lint unit_tests
|
||||
|
||||
test-shellcheck: $(SH_TO_CHECK)
|
||||
|
||||
unit_tests:
|
||||
echo TODO
|
||||
|
||||
$(SH_TO_CHECK):
|
||||
docker run --rm -v $(shell pwd):/mnt \
|
||||
nlknguyen/alpine-shellcheck -x /mnt/$(@)
|
||||
|
||||
.PHONY: test clean $(SH_TO_CHECK) test-shellcheck tests lint build_collator \
|
||||
run_collator run_images all build_docs docs check-docker images
|
99
helm-chart-collator/README.md
Normal file
99
helm-chart-collator/README.md
Normal file
@ -0,0 +1,99 @@
|
||||
# Helm Chart Collator
|
||||
|
||||
The Helm Chart Collator is used to create a Helm Chart Repository served from a Docker
|
||||
image via Chartmuseum. It allows a developer to request charts to be pulled from various
|
||||
locations and packaged into the resulting Docker image, which can then be used as a
|
||||
portable Helm Repository.
|
||||
|
||||
## Setup
|
||||
|
||||
Charts can be sourced from various locations. Each entry must be recorded in a
|
||||
user-defined file before building the image. When the list of charts has been created,
|
||||
the `build-image.sh` script can be used to create the image via the command:
|
||||
|
||||
```
|
||||
./build-image.sh $CHARTSFILE
|
||||
```
|
||||
|
||||
### Charts from Helm Repos
|
||||
|
||||
To pull a chart a from pre-existing Helm Repos by listing them under the `helm_repos`
|
||||
heading. Each listing must include the following:
|
||||
|
||||
* `repo`: The name of the Helm Repo to add (e.g. `stable`)
|
||||
* `url`: The URL where the Helm Repo is hosted (e.g. `https://kubernetes-charts.storage.googleapis.com`)
|
||||
* `name`: The name of the desired chart (e.g. `mariadb`)
|
||||
* `version`: The version of the desired chart (e.g. `7.3.14`)
|
||||
|
||||
|
||||
### Charts from Git Repos
|
||||
|
||||
A Chart can be pulled and packaged from a git repo by listing it under the `git_repos`
|
||||
heading. Listings must include:
|
||||
|
||||
* `name`: The name of the repository (e.g. `openstack-helm`). Note that this is simply
|
||||
used for caching during the cloning process.
|
||||
* `path`: The path to the desired chart within the repo (e.g. `keystone`)
|
||||
* `url`: The URL where the git repo is hosted (e.g. `https://github.com/openstack/openstack-helm`)
|
||||
* `sha`: The SHA-1 of the commit from which the chart should be pulled (e.g. `30c9f003d227b799c636458dea161e24d5823c33`). (default: `HEAD`).
|
||||
* `refspec`: The refspec associated with the `sha`. This is only required if the `sha`
|
||||
can't be reached from the default (e.g. `refs/heads/master`)
|
||||
* `chart_version`: The version to package the chart with (e.g. `1.2.3`)
|
||||
|
||||
If a chart in a git repo specifies dependencies which are not accessible, the
|
||||
dependencies must also be listed under the `dependencies` heading. Dependencies have the
|
||||
same fields as git repos.
|
||||
|
||||
### Charts from Tarballs
|
||||
|
||||
A chart can be downloaded by listing it under the `tarred_charts` header. They
|
||||
require the following:
|
||||
|
||||
* `url`: The URL from which the chart can be downloaded
|
||||
|
||||
## Example
|
||||
|
||||
The following shows an example file for including various helm charts:
|
||||
* rook-ceph as a tarball from a git repo
|
||||
* mariadb from the helm stable repo
|
||||
* rook-ceph from the rook repo
|
||||
* prometheus from the helm/charts git repo
|
||||
* keystone from the openstack-helm git repo
|
||||
* The helm-toolkit is also pulled, since it is a dependency of keystone
|
||||
|
||||
```
|
||||
tarred_charts:
|
||||
- url: https://github.com/project-azorian/rook-ceph-aio/raw/master/rook-ceph-aio/charts/rook-ceph-0.0.1.tgz
|
||||
helm_repos:
|
||||
- repo: stable
|
||||
url: https://kubernetes-charts.storage.googleapis.com
|
||||
name: mariadb
|
||||
version: 7.3.14
|
||||
- repo: rook-release
|
||||
url: https://charts.rook.io/release
|
||||
name: rook-ceph
|
||||
version: v1.3.6
|
||||
git_repos:
|
||||
- name: helm-stable
|
||||
path: stable/prometheus
|
||||
url: https://github.com/helm/charts
|
||||
sha: 79066e1f0f5ce735aeb4783f2adf4b85992d15de
|
||||
# Note: refspec is only needed when if the given sha is not already available
|
||||
refspec: refs/heads/master
|
||||
- name: openstack-helm
|
||||
path: keystone
|
||||
url: https://github.com/openstack/openstack-helm
|
||||
sha: 30c9f003d227b799c636458dea161e24d5823c33
|
||||
chart_version: 1.2.3
|
||||
dependencies:
|
||||
- name: openstack-helm-infra
|
||||
path: helm-toolkit
|
||||
url: https://github.com/openstack/openstack-helm-infra
|
||||
sha: b1e66fd308b6bc9df090aebb5b3807a0df2d87dd
|
||||
```
|
||||
|
||||
Once this file has been created, the image can be built with the following:
|
||||
|
||||
```
|
||||
./build-image.sh charts.yaml
|
||||
```
|
8
helm-chart-collator/build-image.sh
Executable file
8
helm-chart-collator/build-image.sh
Executable file
@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [[ $# != 1 ]]; then
|
||||
printf "usage: ./%s <filename>\n" "$0"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
docker build . -t helm-chart-collator --build-arg "CHARTS=\"$(cat "$1")\""
|
28
helm-chart-collator/examples/charts.yaml
Normal file
28
helm-chart-collator/examples/charts.yaml
Normal file
@ -0,0 +1,28 @@
|
||||
tarred_charts:
|
||||
- url: https://github.com/project-azorian/rook-ceph-aio/raw/master/rook-ceph-aio/charts/rook-ceph-0.0.1.tgz
|
||||
helm_repos:
|
||||
- repo: stable
|
||||
url: https://kubernetes-charts.storage.googleapis.com
|
||||
name: mariadb
|
||||
version: 7.3.14
|
||||
- repo: rook-release
|
||||
url: https://charts.rook.io/release
|
||||
name: rook-ceph
|
||||
version: v1.3.6
|
||||
git_repos:
|
||||
- name: helm-stable
|
||||
path: stable/prometheus
|
||||
url: https://github.com/helm/charts
|
||||
sha: 79066e1f0f5ce735aeb4783f2adf4b85992d15de
|
||||
# Note: refspec is only needed when if the given sha is not already available
|
||||
refspec: refs/heads/master
|
||||
- name: openstack-helm
|
||||
path: keystone
|
||||
url: https://github.com/openstack/openstack-helm
|
||||
sha: 30c9f003d227b799c636458dea161e24d5823c33
|
||||
chart_version: 1.2.3
|
||||
dependencies:
|
||||
- name: openstack-helm-infra
|
||||
path: helm-toolkit
|
||||
url: https://github.com/openstack/openstack-helm-infra
|
||||
sha: b1e66fd308b6bc9df090aebb5b3807a0df2d87dd
|
33
helm-chart-collator/playbooks/create_repository.yaml
Normal file
33
helm-chart-collator/playbooks/create_repository.yaml
Normal file
@ -0,0 +1,33 @@
|
||||
---
|
||||
- hosts: all
|
||||
tasks:
|
||||
|
||||
- name: create charts directory
|
||||
file:
|
||||
path: /charts
|
||||
state: directory
|
||||
|
||||
- include_role:
|
||||
name: ensure_helm
|
||||
|
||||
- include_role:
|
||||
name: install_helm_repo_charts
|
||||
loop: "{{ CHARTS | from_yaml | json_query('helm_repos[*]') | default([], true) }}"
|
||||
loop_control:
|
||||
loop_var: chart
|
||||
|
||||
- include_role:
|
||||
name: install_git_repo_charts
|
||||
loop: "{{ CHARTS | from_yaml | json_query('git_repos[*]') | default([], true) }}"
|
||||
loop_control:
|
||||
loop_var: chart
|
||||
|
||||
- include_role:
|
||||
name: install_tarred_charts
|
||||
loop: "{{ CHARTS | from_yaml | json_query('tarred_charts[*]') | default([], true) }}"
|
||||
loop_control:
|
||||
loop_var: chart
|
||||
|
||||
- name: create index.yaml
|
||||
shell:
|
||||
cmd: helm repo index /charts > /charts/index.yaml
|
5
helm-chart-collator/playbooks/inventory.yaml
Normal file
5
helm-chart-collator/playbooks/inventory.yaml
Normal file
@ -0,0 +1,5 @@
|
||||
all:
|
||||
hosts:
|
||||
localhost:
|
||||
ansible_connection: local
|
||||
ansible_python_interpreter: /usr/bin/python3
|
@ -0,0 +1,12 @@
|
||||
---
|
||||
- name: download and unarchive helm
|
||||
unarchive:
|
||||
src: https://get.helm.sh/helm-v3.2.3-linux-amd64.tar.gz
|
||||
remote_src: yes
|
||||
dest: /
|
||||
|
||||
- name: move helm into the path
|
||||
command: mv /linux-amd64/helm /bin/helm
|
||||
|
||||
- name: assert helm is executable
|
||||
command: helm version
|
@ -0,0 +1,18 @@
|
||||
---
|
||||
- name: clone dependency repo
|
||||
git:
|
||||
dest: /tmp/{{ chart_dependency["name"] }}
|
||||
repo: "{{ chart_dependency['url'] }}"
|
||||
version: "{{ chart_dependency['sha'] | default('HEAD') }}"
|
||||
refspec: "{{ chart_dependency['refspec'] | default('refs/heads/master') }}"
|
||||
depth: 1
|
||||
|
||||
- name: ensure the parent's charts directory exists
|
||||
file:
|
||||
path: /tmp/{{ chart["name"] }}/{{ chart["path"] }}/charts
|
||||
state: directory
|
||||
|
||||
- name: move dependency into parent's charts directory
|
||||
local_action: >-
|
||||
command cp -r /tmp/{{ chart_dependency["name"] }}/{{ chart_dependency["path"] }}
|
||||
/tmp/{{ chart["name"] }}/{{ chart["path"] }}/charts
|
@ -0,0 +1,30 @@
|
||||
---
|
||||
- name: clone repos
|
||||
git:
|
||||
dest: /tmp/{{ chart['name'] }}
|
||||
repo: "{{ chart['url'] }}"
|
||||
version: "{{ chart['sha'] | default('HEAD') }}"
|
||||
refspec: "{{ chart['refspec'] | default('refs/heads/master') }}"
|
||||
depth: 1
|
||||
|
||||
- include_tasks: dependencies.yaml
|
||||
loop: "{{ chart['dependencies'] | default([]) }}"
|
||||
loop_control:
|
||||
loop_var: chart_dependency
|
||||
|
||||
- name: create unique chart version
|
||||
shell:
|
||||
executable: /bin/bash
|
||||
cmd: |
|
||||
sha=$(sha256sum <<< "{{ chart | to_json }}" | cut -f1 -d' ')
|
||||
version=$(helm show chart /tmp/{{ chart['name'] | quote }}/{{ chart['path'] | quote }} | yq -r .version)
|
||||
printf "%s+source.%s" "$version" "$sha"
|
||||
register: chart_version
|
||||
|
||||
- name: package charts into /charts directory
|
||||
shell:
|
||||
cmd: >
|
||||
helm package --destination=/charts
|
||||
{{ '--dependency-update' if not chart.get('dependencies') }}
|
||||
{{ '--version=' + chart.get('chart_version', chart_version.stdout) }}
|
||||
/tmp/{{ chart['name'] }}/{{ chart['path'] }}
|
@ -0,0 +1,8 @@
|
||||
---
|
||||
- name: setup repositories
|
||||
command: helm repo add {{ chart["repo"] }} {{ chart["url"] }}
|
||||
|
||||
- name: pull charts
|
||||
command: helm pull {{ chart["repo"] }}/{{ chart["name"] }} \
|
||||
--destination=/charts \
|
||||
--version={{ chart["version"] }}
|
@ -0,0 +1,5 @@
|
||||
---
|
||||
- name: download chart
|
||||
get_url:
|
||||
dest: /charts
|
||||
url: "{{ chart['url'] }}"
|
Loading…
x
Reference in New Issue
Block a user