def readAndPrintStreamingBuildStatus(user, response): jsonSegmentBytes = b'' output = b'' byte = response.read(1) while byte: jsonSegmentBytes += byte output += byte byte = response.read(1) try: lineDict = json.loads(jsonSegmentBytes.decode("utf-8")) if lineDict == {}: pass elif "stream" in lineDict: user.getRegistry().log(lineDict["stream"]) elif "status" in lineDict: user.getRegistry().log(lineDict["status"]) elif "errorDetail" in lineDict: raise exceptions.ImageBuildException( "Build error:" + lineDict["errorDetail"]["message"] + "\n" + response.read().decode()) else: raise exceptions.ImageBuildException( "Build error:" + jsonSegmentBytes.decode("utf-8") + "\n" + response.read().decode("utf-8")) jsonSegmentBytes = b'' except ValueError: pass return output.decode("utf-8")
def getDependency(self): """ Returns the dependency of this ImageSource as a ImageSource. Or None if there is no dependency. """ if not self.getImageFileType() == "SubuserImagefile": return None subuserImagefileContents = self.getImageFileContents() lineNumber = 0 for line in subuserImagefileContents.split("\n"): if line.startswith("FROM-SUBUSER-IMAGE"): try: import subuserlib.resolve imageURI = line.split(" ")[1] return subuserlib.resolve.resolveImageSource( self.getUser(), imageURI, contextRepository=self.getRepository(), allowLocalRepositories=False ) #TODO, ImageSource names with spaces or other funny characters... except IndexError: raise exceptions.ImageBuildException( "Syntax error in SubuserImagefile one line " + str(lineNumber) + ":\n" + line) except KeyError: raise exceptions.ImageBuildException( "Error in " + self.getName() + "'s SubuserImagefile on line " + str(lineNumber) + "\n Subuser image does not exist: \"" + imageURI + "\"") lineNumber += 1 return None
def build(self,relativeBuildContextPath=None,repositoryFileStructure=None,useCache=True,rm=True,forceRm=True,quiet=False,tag=None,dockerfile=None,quietClient=False): """ Build a Docker image. If a the dockerfile argument is set to a string, use that string as the Dockerfile. Returns the newly created images Id or raises an exception if the build fails. Most of the options are passed directly on to Docker. The quietClient option makes it so that this function does not print any of Docker's status messages when building. """ # Inspired by and partialy taken from https://github.com/docker/docker-py queryParameters = { 'q': "true" if quiet else "false", 'nocache': "false" if useCache else "true", 'rm': "true" if rm else "false", 'forcerm': "true" if forceRm else "false" } if tag: queryParameters["t"] = tag queryParametersString = urllib.parse.urlencode(queryParameters) excludePatterns = [] if relativeBuildContextPath and repositoryFileStructure: dockerignore = "./.dockerignore" if repositoryFileStructure.exists(dockerignore): exclude = list(filter(bool, repositoryFileStructure.read(dockerignore).split('\n'))) with tempfile.NamedTemporaryFile() as tmpArchive: archiveBuildContext(tmpArchive,relativeBuildContextPath=relativeBuildContextPath,repositoryFileStructure=repositoryFileStructure,excludePatterns=excludePatterns,dockerfile=dockerfile) query = "/v1.18/build?"+queryParametersString self.user.registry.log(query) self.getConnection().request("POST",query,body=tmpArchive) try: response = self.getConnection().getresponse() except httplib.ResponseNotReady as rnr: raise exceptions.ImageBuildException(rnr) if response.status != 200: if quietClient: response.read() else: readAndPrintStreamingBuildStatus(self.user, response) raise exceptions.ImageBuildException("Building image failed.\n" +"status: "+str(response.status)+"\n" +"Reason: "+response.reason+"\n") if quietClient: output = response.read().decode("utf-8") else: output = readAndPrintStreamingBuildStatus(self.user,response) # Now we move to regex code stolen from the official python Docker bindings. This is REALLY UGLY! outputLines = output.split("\n") search = r'Successfully built ([0-9a-f]+)' #This is REALLY ugly! match = None for line in reversed(outputLines): match = re.search(search, line) #This is REALLY ugly! if match: break if not match: raise exceptions.ImageBuildException("Unexpected server response when building image. \n " + output) shortId = match.group(1) #This is REALLY ugly! return self.getImageProperties(shortId)["Id"]
def getImageDir(self): if self.__explicitConfig: return self.__explicitConfig["build-context"] imageDir = os.path.join(self.getRelativeSourceDir(),"image") # If the image dir does not exist, # Look for the old, deprecated, docker-image dir if not self.getRepository().getFileStructure().exists(imageDir): imageDir = os.path.join(self.getRelativeSourceDir(),"docker-image") if not self.getRepository().getFileStructure().exists(imageDir): raise exceptions.ImageBuildException("Image source "+self.getIdentifier()+ " does not have an image dir with sources from which to build.") return imageDir