diff --git a/Dockerfile b/Dockerfile index f3626dc8d..da67626d2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,7 +6,14 @@ VOLUME /etc/letsencrypt /var/lib/letsencrypt WORKDIR /opt/certbot COPY CHANGELOG.md README.rst setup.py src/ -COPY letsencrypt-auto-source/pieces/dependency-requirements.txt . + +# Generate constraints file to pin dependency versions +COPY letsencrypt-auto-source/pieces/dependency-requirements.txt hashed_requirements.txt +COPY tools /opt/certbot/tools +RUN /opt/certbot/tools/docker_constraints.py \ + hashed_requirements.txt unhashed_requirements.txt \ + tools/dev_constraints.txt docker_constraints.txt + COPY acme src/acme COPY certbot src/certbot @@ -22,8 +29,9 @@ RUN apk add --no-cache --virtual .build-deps \ openssl-dev \ musl-dev \ libffi-dev \ - && pip install -r /opt/certbot/dependency-requirements.txt \ && pip install --no-cache-dir \ + --requirement /opt/certbot/unhashed_requirements.txt \ + --constraint /opt/certbot/docker_constraints.txt \ --editable /opt/certbot/src/acme \ --editable /opt/certbot/src \ && apk del .build-deps diff --git a/certbot-dns-cloudflare/Dockerfile b/certbot-dns-cloudflare/Dockerfile index 27dcc8751..69a367407 100644 --- a/certbot-dns-cloudflare/Dockerfile +++ b/certbot-dns-cloudflare/Dockerfile @@ -2,4 +2,4 @@ FROM certbot/certbot COPY . src/certbot-dns-cloudflare -RUN pip install --no-cache-dir --editable src/certbot-dns-cloudflare +RUN pip install -c docker_constraints.txt --no-cache-dir --editable src/certbot-dns-cloudflare diff --git a/tools/dev_constraints.txt b/tools/dev_constraints.txt index 88340cb00..f9ad7329b 100644 --- a/tools/dev_constraints.txt +++ b/tools/dev_constraints.txt @@ -1,4 +1,4 @@ -# Specifies Python package versions for development. +# Specifies Python package versions for development and building Docker images. # It includes in particular packages not specified in letsencrypt-auto's requirements file. # Some dev package versions specified here may be overridden by higher level constraints # files during tests (eg. letsencrypt-auto-source/pieces/dependency-requirements.txt). diff --git a/tools/docker_constraints.py b/tools/docker_constraints.py new file mode 100755 index 000000000..b00bd12de --- /dev/null +++ b/tools/docker_constraints.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python +"""Generates constraints file to pin dependency versions in Docker images. + +Removes hashes from supplied requirements file and merges it with existing +constraints file. Versions in requirements take precedence over constraints. + +Generates interstitial with hashes stripped from requirements. +""" + +import sys + +import pip_install +import merge_requirements + +def main(hashed_reqs_in, unhashed_reqs_out, + constraints_in, constraints_out): + with open(unhashed_reqs_out, 'w') as fd: + fd.write(pip_install.remove_requirements_hashes(hashed_reqs_in)) + with open(constraints_out, 'w') as fd: + fd.write(merge_requirements.main(constraints_in, unhashed_reqs_out)) + +if __name__ == '__main__': + main(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4]) diff --git a/tools/pip_install.py b/tools/pip_install.py index dd6302b48..255cee59f 100755 --- a/tools/pip_install.py +++ b/tools/pip_install.py @@ -40,17 +40,23 @@ def certbot_oldest_processing(tools_path, args, test_constraints): return requirements +def remove_requirements_hashes(filename): + out_lines = [] + with open(filename, 'r') as fd: + in_data = fd.readlines() + for line in in_data: + search = re.search(r'^(\S*==\S*).*$', line) + if search: + out_lines.append(search.group(1)) + return os.linesep.join(out_lines) + + def certbot_normal_processing(tools_path, test_constraints): repo_path = os.path.dirname(tools_path) certbot_requirements = os.path.normpath(os.path.join( repo_path, 'letsencrypt-auto-source/pieces/dependency-requirements.txt')) - with open(certbot_requirements, 'r') as fd: - data = fd.readlines() with open(test_constraints, 'w') as fd: - for line in data: - search = re.search(r'^(\S*==\S*).*$', line) - if search: - fd.write('{0}{1}'.format(search.group(1), os.linesep)) + fd.write(remove_requirements_hashes(certbot_requirements)) def merge_requirements(tools_path, requirements, test_constraints, all_constraints):