2014-11-11 23:23:15 +00:00
|
|
|
import tarfile
|
2014-11-12 19:03:07 +00:00
|
|
|
import requests
|
|
|
|
import os
|
2014-11-11 23:23:15 +00:00
|
|
|
|
|
|
|
from tempfile import TemporaryFile, mkdtemp
|
|
|
|
from zipfile import ZipFile
|
2014-11-18 20:45:56 +00:00
|
|
|
from util.dockerfileparse import parse_dockerfile
|
|
|
|
from util.safetar import safe_extractall
|
2014-11-11 23:23:15 +00:00
|
|
|
|
|
|
|
class BuildPackageException(Exception):
|
|
|
|
""" Exception raised when retrieving or parsing a build package. """
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
class BuildPackage(object):
|
|
|
|
""" Helper class for easy reading and updating of a Dockerfile build pack. """
|
|
|
|
|
2014-11-18 20:45:56 +00:00
|
|
|
def __init__(self, requests_file):
|
2014-11-11 23:23:15 +00:00
|
|
|
self._mime_processors = {
|
2014-11-18 20:45:56 +00:00
|
|
|
'application/zip': BuildPackage.__prepare_zip,
|
|
|
|
'application/x-zip-compressed': BuildPackage.__prepare_zip,
|
|
|
|
'text/plain': BuildPackage.__prepare_dockerfile,
|
|
|
|
'application/octet-stream': BuildPackage.__prepare_dockerfile,
|
|
|
|
'application/x-tar': BuildPackage.__prepare_tarball,
|
|
|
|
'application/gzip': BuildPackage.__prepare_tarball,
|
|
|
|
'application/x-gzip': BuildPackage.__prepare_tarball,
|
2014-11-11 23:23:15 +00:00
|
|
|
}
|
|
|
|
|
2014-11-12 19:03:07 +00:00
|
|
|
c_type = requests_file.headers['content-type']
|
2014-11-11 23:23:15 +00:00
|
|
|
c_type = c_type.split(';')[0] if ';' in c_type else c_type
|
|
|
|
|
|
|
|
if c_type not in self._mime_processors:
|
|
|
|
raise BuildPackageException('Unknown build package mime type: %s' % c_type)
|
|
|
|
|
|
|
|
self._package_directory = None
|
|
|
|
try:
|
|
|
|
self._package_directory = self._mime_processors[c_type](requests_file)
|
|
|
|
except Exception as ex:
|
|
|
|
raise BuildPackageException(ex.message)
|
|
|
|
|
2014-11-12 19:03:07 +00:00
|
|
|
def parse_dockerfile(self, subdirectory):
|
2014-11-11 23:23:15 +00:00
|
|
|
dockerfile_path = os.path.join(self._package_directory, subdirectory, 'Dockerfile')
|
|
|
|
if not os.path.exists(dockerfile_path):
|
|
|
|
if subdirectory:
|
|
|
|
message = 'Build package did not contain a Dockerfile at sub directory %s.' % subdirectory
|
|
|
|
else:
|
|
|
|
message = 'Build package did not contain a Dockerfile at the root directory.'
|
|
|
|
|
|
|
|
raise BuildPackageException(message)
|
|
|
|
|
|
|
|
with open(dockerfile_path, 'r') as dockerfileobj:
|
|
|
|
return parse_dockerfile(dockerfileobj.read())
|
|
|
|
|
2014-11-12 19:03:07 +00:00
|
|
|
@staticmethod
|
2014-11-11 23:23:15 +00:00
|
|
|
def from_url(url):
|
2014-11-12 19:03:07 +00:00
|
|
|
buildpack_resource = requests.get(url, stream=True)
|
|
|
|
return BuildPackage(buildpack_resource)
|
2014-11-11 23:23:15 +00:00
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def __prepare_zip(request_file):
|
|
|
|
build_dir = mkdtemp(prefix='docker-build-')
|
|
|
|
|
|
|
|
# Save the zip file to temp somewhere
|
|
|
|
with TemporaryFile() as zip_file:
|
|
|
|
zip_file.write(request_file.content)
|
|
|
|
to_extract = ZipFile(zip_file)
|
|
|
|
to_extract.extractall(build_dir)
|
|
|
|
|
|
|
|
return build_dir
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def __prepare_dockerfile(request_file):
|
|
|
|
build_dir = mkdtemp(prefix='docker-build-')
|
|
|
|
dockerfile_path = os.path.join(build_dir, "Dockerfile")
|
|
|
|
with open(dockerfile_path, 'w') as dockerfile:
|
|
|
|
dockerfile.write(request_file.content)
|
|
|
|
|
|
|
|
return build_dir
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def __prepare_tarball(request_file):
|
|
|
|
build_dir = mkdtemp(prefix='docker-build-')
|
|
|
|
|
|
|
|
# Save the zip file to temp somewhere
|
|
|
|
with tarfile.open(mode='r|*', fileobj=request_file.raw) as tar_stream:
|
|
|
|
safe_extractall(tar_stream, build_dir)
|
|
|
|
|
2014-11-18 20:45:56 +00:00
|
|
|
return build_dir
|