1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-08-07 23:05:26 +02:00

fix(app): registry push-pull features overhaul (#3393)

* feat(registry): registry or direct url selector

* feat(app): push pull container creation

* feat(app): push pull container duplicate

* feat(app): push pull container details recreate

* feat(app): push pull container details commit

* feat(app): push pull images

* feat(app): push pull image tag

* feat(app): push pull image push

* feat(app): push pull image pull

* feat(app): push pull service creation

* feat(app): push pull templates create container

* feat(app): push pull templates create stacks

* feat(app): push pull template edit

* feat(app): push pull service details update

* fix(app): refactor registry selector + registry auto select

* feat(app): remove autocomplete on registry selector

* style(image-registry): reword simple/advanced mode

* Revert "feat(app): remove autocomplete on registry selector"

This reverts commit 97ec2ddd62.

* refactor(registry-selector): reverse registry and image fields

* feat(app): autocomplete on registry selector

* feat(registry-selector): change gitlab registry autocomplete

* feat(registry-selector): autocomplete for dockerhub

* feat(registry-selector): gitlab url based on locked value instead of name

* fix(registry-selector): gitlab registries URL are not modified anymore

* fix(registry-selector): change gitlab image autofill on duplicate

* fix(registry-selector): gitlab registries now only suggest their own images and not all from gitlab

* fix(registry-selector): psuh pull issues with gitlab registries

* fix(registry-selector): dockerhub registry selection on duplicate for dockerhub images

* fix(templates): registry retrieval for template

* feat(images): add autocomplete on image pull panel

* fix(registry-selector): add latest tag when no tag is specified

* fix(registry-selector): latest tag now applied for non gitlab registries
This commit is contained in:
xAt0mZ 2019-11-27 23:36:39 +01:00 committed by Anthony Lapenna
parent 61c38534a7
commit e19bc8abc7
32 changed files with 525 additions and 349 deletions

View file

@ -2,6 +2,7 @@ import _ from 'lodash-es';
import { ContainerCapabilities, ContainerCapability } from '../../../models/containerCapabilities';
import { AccessControlFormData } from '../../../../portainer/components/accessControlForm/porAccessControlFormModel';
import { ContainerDetailsViewModel } from '../../../models/container';
import { PorImageRegistryModel } from 'Docker/models/porImageRegistry';
angular.module('portainer.docker')
@ -27,7 +28,8 @@ function ($q, $scope, $async, $state, $timeout, $transition$, $filter, Container
NodeName: null,
capabilities: [],
LogDriverName: '',
LogDriverOpts: []
LogDriverOpts: [],
RegistryModel: new PorImageRegistryModel()
};
$scope.extraNetworks = {};
@ -130,11 +132,8 @@ function ($q, $scope, $async, $state, $timeout, $transition$, $filter, Container
$scope.fromContainerMultipleNetworks = false;
function prepareImageConfig(config) {
var image = config.Image;
var registry = $scope.formValues.Registry;
var imageConfig = ImageHelper.createImageConfigForContainer(image, registry.URL);
config.Image = imageConfig.fromImage + ':' + imageConfig.tag;
$scope.imageConfig = imageConfig;
const imageConfig = ImageHelper.createImageConfigForContainer($scope.formValues.RegistryModel);
config.Image = imageConfig.fromImage;
}
function preparePortBindings(config) {
@ -438,13 +437,9 @@ function ($q, $scope, $async, $state, $timeout, $transition$, $filter, Container
}
function loadFromContainerImageConfig() {
var imageInfo = ImageHelper.extractImageAndRegistryFromRepository($scope.config.Image);
RegistryService.retrieveRegistryFromRepository($scope.config.Image)
.then(function success(data) {
if (data) {
$scope.config.Image = imageInfo.image;
$scope.formValues.Registry = data;
}
RegistryService.retrievePorRegistryModelFromRepository($scope.config.Image)
.then((model) => {
$scope.formValues.RegistryModel = model;
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrive registry');
@ -569,7 +564,6 @@ function ($q, $scope, $async, $state, $timeout, $transition$, $filter, Container
loadFromContainerSpec();
} else {
$scope.fromContainer = {};
$scope.formValues.Registry = {};
$scope.formValues.capabilities = new ContainerCapabilities();
}
}, function(e) {
@ -754,7 +748,7 @@ function ($q, $scope, $async, $state, $timeout, $transition$, $filter, Container
function pullImageIfNeeded() {
return $q.when($scope.formValues.alwaysPull &&
ImageService.pullImage($scope.config.Image, $scope.formValues.Registry, true));
ImageService.pullImage($scope.formValues.RegistryModel, true));
}
function createNewContainer() {

View file

@ -21,18 +21,18 @@
<div class="col-sm-12 form-section-title">
Image configuration
</div>
<div ng-if="!formValues.Registry && fromContainer">
<div ng-if="!formValues.RegistryModel.Registry && fromContainer">
<i class="fa fa-exclamation-triangle orange-icon" aria-hidden="true"></i>
<span class="small text-danger" style="margin-left: 5px;">The Docker registry for the <code>{{ config.Image }}</code> image is not registered inside Portainer, you will not be able to create a container. Please register that registry first.</span>
</div>
<div ng-if="formValues.Registry || !fromContainer">
<div ng-if="formValues.RegistryModel.Registry || !fromContainer">
<!-- image-and-registry -->
<por-image-registry
image="config.Image"
registry="formValues.Registry"
ng-if="formValues.Registry"
model="formValues.RegistryModel"
pull-warning="formValues.alwaysPull"
ng-if="formValues.RegistryModel.Registry"
auto-complete="true"
label-class="col-sm-1" input-class="col-sm-11 col-md-5"
label-class="col-sm-1" input-class="col-sm-11"
></por-image-registry>
<!-- !image-and-registry -->
<!-- always-pull -->
@ -142,7 +142,9 @@
<!-- !autoremove -->
<div class="form-group">
<div class="col-sm-12">
<button type="button" class="btn btn-primary btn-sm" ng-disabled="state.actionInProgress || !config.Image || (!formValues.Registry && fromContainer)" ng-click="create()" button-spinner="state.actionInProgress">
<button type="button" class="btn btn-primary btn-sm"
ng-disabled="state.actionInProgress || !formValues.RegistryModel.Image || (!formValues.RegistryModel.Registry && fromContainer)"
ng-click="create()" button-spinner="state.actionInProgress">
<span ng-hide="state.actionInProgress">Deploy the container</span>
<span ng-show="state.actionInProgress">Deployment in progress...</span>
</button>

View file

@ -155,10 +155,9 @@
<!-- !tag-description -->
<!-- image-and-registry -->
<por-image-registry
image="config.Image"
registry="config.Registry"
model="config.RegistryModel"
auto-complete="true"
label-class="col-sm-1" input-class="col-sm-11 col-md-5"
label-class="col-sm-1" input-class="col-sm-11"
></por-image-registry>
<!-- !image-and-registry -->
<!-- tag-note -->
@ -170,7 +169,7 @@
<!-- !tag-note -->
<div class="form-group">
<div class="col-sm-12">
<button type="button" class="btn btn-primary btn-sm" ng-disabled="!config.Image" ng-click="commit()">Create</button>
<button type="button" class="btn btn-primary btn-sm" ng-disabled="!config.RegistryModel.Image || config.commitInProgress" ng-click="commit()">Create</button>
</div>
</div>
</form>

View file

@ -1,14 +1,15 @@
import moment from 'moment';
import { PorImageRegistryModel } from 'Docker/models/porImageRegistry';
angular.module('portainer.docker')
.controller('ContainerController', ['$q', '$scope', '$state','$transition$', '$filter', 'Commit', 'ContainerHelper', 'ContainerService', 'ImageHelper', 'NetworkService', 'Notifications', 'ModalService', 'ResourceControlService', 'RegistryService', 'ImageService', 'HttpRequestHelper', 'Authentication',
function ($q, $scope, $state, $transition$, $filter, Commit, ContainerHelper, ContainerService, ImageHelper, NetworkService, Notifications, ModalService, ResourceControlService, RegistryService, ImageService, HttpRequestHelper, Authentication) {
.controller('ContainerController', ['$q', '$scope', '$state','$transition$', '$filter', '$async', 'Commit', 'ContainerHelper', 'ContainerService', 'ImageHelper', 'NetworkService', 'Notifications', 'ModalService', 'ResourceControlService', 'RegistryService', 'ImageService', 'HttpRequestHelper', 'Authentication',
function ($q, $scope, $state, $transition$, $filter, $async, Commit, ContainerHelper, ContainerService, ImageHelper, NetworkService, Notifications, ModalService, ResourceControlService, RegistryService, ImageService, HttpRequestHelper, Authentication) {
$scope.activityTime = 0;
$scope.portBindings = [];
$scope.config = {
Image: '',
Registry: ''
RegistryModel: new PorImageRegistryModel(),
commitInProgress: false
};
$scope.state = {
@ -149,20 +150,23 @@ function ($q, $scope, $state, $transition$, $filter, Commit, ContainerHelper, Co
});
};
$scope.commit = function () {
var image = $scope.config.Image;
$scope.config.Image = '';
var registry = $scope.config.Registry;
var imageConfig = ImageHelper.createImageConfigForCommit(image, registry.URL);
Commit.commitContainer({id: $transition$.params().id, tag: imageConfig.tag, repo: imageConfig.repo}, function () {
update();
async function commitContainerAsync() {
$scope.config.commitInProgress = true;
const registryModel = $scope.config.RegistryModel;
const imageConfig = ImageHelper.createImageConfigForContainer(registryModel);
try {
await Commit.commitContainer({id: $transition$.params().id, repo: imageConfig.fromImage}).$promise;
Notifications.success('Image created', $transition$.params().id);
}, function (e) {
update();
Notifications.error('Failure', e, 'Unable to create image');
});
};
$state.reload();
} catch (err) {
Notifications.error('Failure', err, 'Unable to create image');
$scope.config.commitInProgress = false;
}
}
$scope.commit = function () {
return $async(commitContainerAsync);
};
$scope.confirmRemove = function () {
var title = 'You are about to remove a container.';
@ -225,15 +229,12 @@ function ($q, $scope, $state, $transition$, $filter, Commit, ContainerHelper, Co
if (!pullImage) {
return $q.when();
}
return getRegistry().then(function pullImage(containerRegistery) {
return ImageService.pullImage(container.Config.Image, containerRegistery, true);
return RegistryService.retrievePorRegistryModelFromRepository(container.Config.Image)
.then(function pullImage(registryModel) {
return ImageService.pullImage(registryModel, true);
});
}
function getRegistry() {
return RegistryService.retrieveRegistryFromRepository(container.Config.Image);
}
function setMainNetworkAndCreateContainer() {
var networks = config.NetworkingConfig.EndpointsConfig;
var networksNames = Object.keys(networks);