2021-06-11 00:05:54 +00:00
|
|
|
angular.module('portainer.docker').controller('BuildImageController', BuildImageController);
|
2021-03-20 21:13:27 +00:00
|
|
|
|
2022-08-04 23:04:26 +00:00
|
|
|
/* @ngInject */
|
2022-11-02 11:29:26 +00:00
|
|
|
function BuildImageController($scope, $async, $window, ModalService, BuildService, Notifications, HttpRequestHelper, endpoint) {
|
|
|
|
$scope.endpoint = endpoint;
|
|
|
|
|
2021-06-11 00:05:54 +00:00
|
|
|
$scope.state = {
|
|
|
|
BuildType: 'editor',
|
|
|
|
actionInProgress: false,
|
|
|
|
activeTab: 0,
|
|
|
|
isEditorDirty: false,
|
|
|
|
};
|
2018-02-28 06:19:06 +00:00
|
|
|
|
2021-06-11 00:05:54 +00:00
|
|
|
$scope.formValues = {
|
2022-08-04 23:04:26 +00:00
|
|
|
ImageNames: [{ Name: '', Valid: false, Unique: true }],
|
2021-06-11 00:05:54 +00:00
|
|
|
UploadFile: null,
|
|
|
|
DockerFileContent: '',
|
2022-09-14 06:47:24 +00:00
|
|
|
AdditionalFiles: [],
|
2021-06-11 00:05:54 +00:00
|
|
|
URL: '',
|
|
|
|
Path: 'Dockerfile',
|
|
|
|
NodeName: null,
|
|
|
|
};
|
2018-02-28 06:19:06 +00:00
|
|
|
|
2021-06-11 00:05:54 +00:00
|
|
|
$window.onbeforeunload = () => {
|
|
|
|
if ($scope.state.BuildType === 'editor' && $scope.formValues.DockerFileContent && $scope.state.isEditorDirty) {
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-08-10 04:44:33 +00:00
|
|
|
$scope.$on('$destroy', function () {
|
|
|
|
$scope.state.isEditorDirty = false;
|
|
|
|
});
|
|
|
|
|
2022-08-04 23:04:26 +00:00
|
|
|
$scope.checkName = function (index) {
|
|
|
|
var item = $scope.formValues.ImageNames[index];
|
|
|
|
item.Valid = true;
|
|
|
|
item.Unique = true;
|
|
|
|
if (item.Name !== '') {
|
|
|
|
// Check unique
|
|
|
|
$scope.formValues.ImageNames.forEach((element, idx) => {
|
|
|
|
if (idx != index && element.Name == item.Name) {
|
|
|
|
item.Valid = false;
|
|
|
|
item.Unique = false;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
if (!item.Valid) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Validation
|
|
|
|
const parts = item.Name.split('/');
|
2022-06-07 08:42:09 +00:00
|
|
|
const repository = parts[parts.length - 1];
|
|
|
|
const repositoryRegExp = RegExp('^[a-z0-9-_]{2,255}(:[A-Za-z0-9-_.]{1,128})?$');
|
2022-08-04 23:04:26 +00:00
|
|
|
item.Valid = repositoryRegExp.test(repository);
|
2022-06-07 08:42:09 +00:00
|
|
|
};
|
|
|
|
|
2021-06-11 00:05:54 +00:00
|
|
|
$scope.addImageName = function () {
|
2022-08-04 23:04:26 +00:00
|
|
|
$scope.formValues.ImageNames.push({ Name: '', Valid: false, Unique: true });
|
2021-06-11 00:05:54 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
$scope.removeImageName = function (index) {
|
|
|
|
$scope.formValues.ImageNames.splice(index, 1);
|
2022-08-04 23:04:26 +00:00
|
|
|
for (var i = 0; i < $scope.formValues.ImageNames.length; i++) {
|
|
|
|
$scope.checkName(i);
|
|
|
|
}
|
2021-06-11 00:05:54 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
function buildImageBasedOnBuildType(method, names) {
|
|
|
|
var buildType = $scope.state.BuildType;
|
|
|
|
var dockerfilePath = $scope.formValues.Path;
|
|
|
|
|
|
|
|
if (buildType === 'upload') {
|
|
|
|
var file = $scope.formValues.UploadFile;
|
|
|
|
return BuildService.buildImageFromUpload(names, file, dockerfilePath);
|
|
|
|
} else if (buildType === 'url') {
|
|
|
|
var URL = $scope.formValues.URL;
|
|
|
|
return BuildService.buildImageFromURL(names, URL, dockerfilePath);
|
|
|
|
} else {
|
|
|
|
var dockerfileContent = $scope.formValues.DockerFileContent;
|
2022-09-14 06:47:24 +00:00
|
|
|
if ($scope.formValues.AdditionalFiles.length === 0) {
|
|
|
|
return BuildService.buildImageFromDockerfileContent(names, dockerfileContent);
|
|
|
|
} else {
|
|
|
|
var additionalFiles = $scope.formValues.AdditionalFiles;
|
|
|
|
return BuildService.buildImageFromDockerfileContentAndFiles(names, dockerfileContent, additionalFiles);
|
|
|
|
}
|
2020-04-10 21:54:53 +00:00
|
|
|
}
|
2021-06-11 00:05:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
$scope.buildImage = buildImage;
|
2018-02-28 06:19:06 +00:00
|
|
|
|
2021-06-11 00:05:54 +00:00
|
|
|
async function buildImage() {
|
|
|
|
return $async(async () => {
|
2020-04-10 21:54:53 +00:00
|
|
|
var buildType = $scope.state.BuildType;
|
2018-02-28 06:19:06 +00:00
|
|
|
|
2020-04-10 21:54:53 +00:00
|
|
|
if (buildType === 'editor' && $scope.formValues.DockerFileContent === '') {
|
|
|
|
$scope.state.formValidationError = 'Dockerfile content must not be empty';
|
|
|
|
return;
|
|
|
|
}
|
2018-02-28 06:19:06 +00:00
|
|
|
|
2020-04-10 21:54:53 +00:00
|
|
|
$scope.state.actionInProgress = true;
|
2018-02-28 06:19:06 +00:00
|
|
|
|
2020-04-10 21:54:53 +00:00
|
|
|
var imageNames = $scope.formValues.ImageNames.filter(function filterNull(x) {
|
|
|
|
return x.Name;
|
|
|
|
}).map(function getNames(x) {
|
|
|
|
return x.Name;
|
|
|
|
});
|
2018-02-28 06:19:06 +00:00
|
|
|
|
2020-04-10 21:54:53 +00:00
|
|
|
var nodeName = $scope.formValues.NodeName;
|
|
|
|
HttpRequestHelper.setPortainerAgentTargetHeader(nodeName);
|
2018-02-28 06:19:06 +00:00
|
|
|
|
2021-06-11 00:05:54 +00:00
|
|
|
try {
|
|
|
|
const data = await buildImageBasedOnBuildType(buildType, imageNames);
|
|
|
|
$scope.buildLogs = data.buildLogs;
|
|
|
|
$scope.state.activeTab = 1;
|
|
|
|
if (data.hasError) {
|
|
|
|
Notifications.error('An error occurred during build', { msg: 'Please check build logs output' });
|
|
|
|
} else {
|
|
|
|
Notifications.success('Image successfully built');
|
|
|
|
$scope.state.isEditorDirty = false;
|
2020-04-10 21:54:53 +00:00
|
|
|
}
|
2021-06-11 00:05:54 +00:00
|
|
|
} catch (err) {
|
|
|
|
Notifications.error('Failure', err, 'Unable to build image');
|
|
|
|
} finally {
|
|
|
|
$scope.state.actionInProgress = false;
|
2020-04-10 21:54:53 +00:00
|
|
|
}
|
2021-06-11 00:05:54 +00:00
|
|
|
});
|
|
|
|
}
|
2018-02-28 06:19:06 +00:00
|
|
|
|
2021-06-11 00:05:54 +00:00
|
|
|
$scope.validImageNames = function () {
|
2022-06-07 08:42:09 +00:00
|
|
|
if ($scope.formValues.ImageNames.length == 0) {
|
|
|
|
return false;
|
|
|
|
}
|
2021-06-11 00:05:54 +00:00
|
|
|
for (var i = 0; i < $scope.formValues.ImageNames.length; i++) {
|
2022-08-04 23:04:26 +00:00
|
|
|
if (!$scope.formValues.ImageNames[i].Valid) {
|
2022-06-07 08:42:09 +00:00
|
|
|
return false;
|
2021-03-20 21:13:27 +00:00
|
|
|
}
|
2021-06-11 00:05:54 +00:00
|
|
|
}
|
2022-06-07 08:42:09 +00:00
|
|
|
return true;
|
2021-06-11 00:05:54 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
$scope.editorUpdate = function (cm) {
|
|
|
|
$scope.formValues.DockerFileContent = cm.getValue();
|
|
|
|
$scope.state.isEditorDirty = true;
|
|
|
|
};
|
|
|
|
|
|
|
|
this.uiCanExit = async function () {
|
|
|
|
if ($scope.state.BuildType === 'editor' && $scope.formValues.DockerFileContent && $scope.state.isEditorDirty) {
|
|
|
|
return ModalService.confirmWebEditorDiscard();
|
|
|
|
}
|
|
|
|
};
|
2022-09-14 06:47:24 +00:00
|
|
|
|
|
|
|
$scope.selectAdditionalFiles = function (files) {
|
|
|
|
$scope.formValues.AdditionalFiles = files;
|
|
|
|
};
|
2021-06-11 00:05:54 +00:00
|
|
|
}
|