/** * Service which provides helper methods for extracting information out from a Dockerfile * or an archive containing a Dockerfile. */ angular.module('quay').factory('DockerfileService', ['DataFileService', 'Config', function(DataFileService, Config) { var dockerfileService = {}; function DockerfileInfo(contents) { this.contents = contents; } DockerfileInfo.prototype.getRegistryBaseImage = function() { var baseImage = this.getBaseImage(); if (!baseImage) { return null; } if (baseImage.indexOf(Config.getDomain() + '/') != 0) { return null; } return baseImage.substring(Config.getDomain().length + 1); }; DockerfileInfo.prototype.getBaseImage = function() { var imageAndTag = this.getBaseImageAndTag(); if (!imageAndTag) { return null; } // Note, we have to handle a few different cases here: // 1) someimage // 2) someimage:tag // 3) host:port/someimage // 4) host:port/someimage:tag var lastIndex = imageAndTag.lastIndexOf(':'); if (lastIndex < 0) { return imageAndTag; } // Otherwise, check if there is a / in the portion after the split point. If so, // then the latter is part of the path (and not a tag). var afterColon = imageAndTag.substring(lastIndex + 1); if (afterColon.indexOf('/') >= 0) { return imageAndTag; } return imageAndTag.substring(0, lastIndex); }; DockerfileInfo.prototype.getBaseImageAndTag = function() { var fromIndex = this.contents.indexOf('FROM '); if (fromIndex < 0) { return null; } var newline = this.contents.indexOf('\n', fromIndex); if (newline < 0) { newline = this.contents.length; } return $.trim(this.contents.substring(fromIndex + 'FROM '.length, newline)); }; DockerfileInfo.forData = function(contents) { if (contents.indexOf('FROM ') < 0) { return; } return new DockerfileInfo(contents); }; var processFiles = function(files, dataArray, success, failure) { // The files array will be empty if the submitted file was not an archive. We therefore // treat it as a single Dockerfile. if (files.length == 0) { DataFileService.arrayToString(dataArray, function(c) { var result = DockerfileInfo.forData(c); if (!result) { failure('File chosen is not a valid Dockerfile'); return; } success(result); }); return; } var found = false; files.forEach(function(file) { if (file['name'] == 'Dockerfile') { DataFileService.blobToString(file.toBlob(), function(c) { var result = DockerfileInfo.forData(c); if (!result) { failure('Dockerfile inside archive is not a valid Dockerfile'); return; } success(result); }); found = true; } }); if (!found) { failure('No Dockerfile found in root of archive'); } }; dockerfileService.getDockerfile = function(file, success, failure) { var reader = new FileReader(); reader.onload = function(e) { var dataArray = reader.result; DataFileService.readDataArrayAsPossibleArchive(dataArray, function(files) { processFiles(files, dataArray, success, failure); }, function() { // Not an archive. Read directly as a single file. processFiles([], dataArray, success, failure); }); }; reader.onerror = failure; reader.readAsArrayBuffer(file); }; return dockerfileService; }]);