From 07470a206d27a021146fa1f5f8598892960b5efa Mon Sep 17 00:00:00 2001 From: Stefan Reimer Date: Thu, 23 Sep 2021 19:27:06 +0200 Subject: [PATCH] feat: add Dockerfile, build tweaks --- Dockerfile | 64 +++++++++++++++++++++++++++++++++++++++++++ Makefile | 21 +++++++++++++- cloudbender/pulumi.py | 16 +++++++++-- requirements.txt | 4 ++- setup.py | 4 +-- 5 files changed, 102 insertions(+), 7 deletions(-) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..d654255 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,64 @@ +ARG RUNTIME_VERSION="3.9" +ARG DISTRO_VERSION="3.14" +ARG PULUMI_VERSION=latest + +FROM python:${RUNTIME_VERSION}-alpine${DISTRO_VERSION} AS builder +ARG PULUMI_VERSION + +RUN apk add --no-cache \ + autoconf \ + automake \ + build-base \ + cmake \ + curl \ + make \ + libc6-compat \ + gcc \ + linux-headers \ + libffi-dev \ + openssl-dev + +RUN if [ "$PULUMI_VERSION" = "latest" ]; then \ + curl -fsSL https://get.pulumi.com/ | sh; \ + else \ + curl -fsSL https://get.pulumi.com/ | sh -s -- --version $PULUMI_VERSION ; \ + fi + +ENV VIRTUAL_ENV=/venv +RUN python -m venv $VIRTUAL_ENV +ENV PATH="$VIRTUAL_ENV/bin:$PATH" + +# Install CloudBender +WORKDIR /app +COPY . /app +RUN pip install -r requirements.txt +RUN pip install . --no-deps + + + +# Now build the final runtime +FROM python:${RUNTIME_VERSION}-alpine${DISTRO_VERSION} + +# Install GCC (Alpine uses musl but we compile and link dependencies with GCC) +RUN apk add --no-cache \ + libstdc++ \ + libc6-compat \ + ca-certificates \ + podman + +COPY --from=builder /venv /venv +COPY --from=builder /root/.pulumi/bin /usr/local/bin +RUN mkdir /workspace && \ + cd /usr/bin && ln -s podman docker && \ + cd /usr/local/bin && \ + rm -f *dotnet *nodejs *go +WORKDIR /workspace + +ENV VIRTUAL_ENV=/venv +ENV PATH="$VIRTUAL_ENV/bin:$PATH" + +# Dont run as root by default +RUN addgroup cloudbender && adduser cloudbender -G cloudbender -D +USER cloudbender + +CMD ["cloudbender"] diff --git a/Makefile b/Makefile index d759fae..8e126b2 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,17 @@ VERSION ?= $(shell grep '__version__' cloudbender/__init__.py | cut -d' ' -f3 | cut -d'-' -f1 | sed -e 's/"//g') PACKAGE_FILE := dist/cloudbender-$(VERSION).py3-none-any.whl -.PHONY: test build test_upload upload all +REGISTRY := public.ecr.aws/zero-downtime +REPOSITORY := cloudbender +TAG := $(REPOSITORY):v$(VERSION) + +.PHONY: test build test_upload upload all dev_setup docker all: test build +dev_setup: + pip install -r requirements.txt --user + test: flake8 --ignore=E501 cloudbender tests TEST=True pytest --log-cli-level=DEBUG @@ -22,3 +29,15 @@ test_upload: $(PACKAGE_FILE) upload: $(PACKAGE_FILE) twine upload --repository-url https://upload.pypi.org/legacy/ dist/cloudbender-*.whl + +docker: + podman build --rm --squash-all --build-arg version=$(VERSION) -t $(TAG) . + +push: + aws ecr-public get-login-password --region us-east-1 | podman login --username AWS --password-stdin $(REGISTRY) + podman tag $(TAG) $(REGISTRY)/$(TAG) + podman push $(REGISTRY)/$(TAG) + +scan: + podman system service& + sleep 3; trivy $(TAG) diff --git a/cloudbender/pulumi.py b/cloudbender/pulumi.py index fb0e035..d1d8d6d 100644 --- a/cloudbender/pulumi.py +++ b/cloudbender/pulumi.py @@ -3,6 +3,7 @@ import os import re import shutil import importlib +import pkg_resources import pulumi import logging @@ -64,12 +65,21 @@ def pulumi_init(stack): except KeyError: raise KeyError('Missing Pulumi securityProvider setting !') + # Set tag for stack file name and version + _tags = stack.tags + try: + _version = _stack.VERSION + except AttributeError: + _version = 'undefined' + + _tags['zero-downtime.net/cloudbender'] = '{}:{}'.format(os.path.basename(_stack.__file__), _version) + _config = { "aws:region": stack.region, "aws:profile": stack.profile, - "aws:defaultTags": {"tags": stack.tags}, + "aws:defaultTags": {"tags": _tags}, "zdt:region": stack.region, - "zdt:awsAccount": account_id, + "zdt:awsAccountId": account_id, } # inject all parameters as config in the namespace @@ -95,6 +105,6 @@ def pulumi_init(stack): secrets_provider=secrets_provider) stack = pulumi.automation.create_or_select_stack(stack_name=pulumi_stackname, project_name=project_name, program=_stack.pulumi_program, opts=ws_opts) - stack.workspace.install_plugin("aws", "4.19.0") + stack.workspace.install_plugin("aws", pkg_resources.get_distribution("pulumi_aws").version) return stack diff --git a/requirements.txt b/requirements.txt index 4a6e3c0..eab027c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,4 +3,6 @@ Jinja2<3 click pyminifier cfn-lint>=0.34 -pulumi +# apprise +pulumi>=3.0.0,<4.0.0 +pulumi-aws>=4.0.0,<5.0.0 diff --git a/setup.py b/setup.py index 075e7cc..f599619 100644 --- a/setup.py +++ b/setup.py @@ -54,10 +54,10 @@ setup( author_email='stefan@zero-downtime.net', url='https://git.zero-downtime.net/ZeroDownTime/CloudBender', packages=find_packages(), - package_data={ 'cloudbender': ['templates/*.md'], }, + package_data={ 'cloudbender': ['templates/*.md', 'templates/*.yaml'], }, include_package_data=True, entry_points={'console_scripts': [ "cloudbender = cloudbender.cli:cli" ]}, - install_requires=['boto3', 'Jinja2', 'click', 'cfn-lint>=0.34', 'pyminifier', 'pulumi'], + install_requires=['boto3', 'Jinja2', 'click', 'cfn-lint>=0.34', 'pyminifier', 'pulumi>=3.0.0,<4.0.0', 'pulumi-aws>=4.0.0,<5.0.0'], #'apprise' tests_require=["pytest-cov", "moto", "mock", 'pytest'], cmdclass={"test": PyTest}, classifiers=[