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

pull/3393/head
xAt0mZ 2019-11-25 19:12:46 +01:00
parent 332aa4fbf5
commit 06c63899b2
9 changed files with 26 additions and 50 deletions

View File

@ -3,6 +3,7 @@ angular.module('portainer.docker').component('porImageRegistry', {
controller: 'porImageRegistryController', controller: 'porImageRegistryController',
bindings: { bindings: {
'model': '=', // must be of type PorImageRegistryModel 'model': '=', // must be of type PorImageRegistryModel
'pullWarning': '<',
'autoComplete': '<', 'autoComplete': '<',
'labelClass': '@', 'labelClass': '@',
'inputClass': '@' 'inputClass': '@'

View File

@ -1,20 +1,10 @@
<div class="form-group">
<div class="col-sm-12">
<label for="use_registry" class="control-label text-left">
Use registry
</label>
<label class="switch" style="margin-left: 20px;">
<input type="checkbox" ng-model="$ctrl.model.UseRegistry"><i></i>
</label>
</div>
</div>
<!-- use registry --> <!-- use registry -->
<div ng-if="$ctrl.model.UseRegistry"> <div ng-if="$ctrl.model.UseRegistry">
<div class="form-group"> <div class="form-group">
<label for="image_name" ng-class="$ctrl.labelClass" class="control-label text-left">Image</label> <label for="image_name" ng-class="$ctrl.labelClass" class="control-label text-left">Image</label>
<div ng-class="$ctrl.inputClass"> <div ng-class="$ctrl.inputClass">
<div class="input-group"> <div class="input-group">
<span class="input-group-addon" id="registry-name">{{$ctrl.model.Registry.URL}}</span> <span class="input-group-addon" id="registry-name">{{$ctrl.model.Registry.URL || 'docker.io'}}</span>
<input type="text" class="form-control" aria-describedby="registry-name" uib-typeahead="image for image in $ctrl.availableImages | filter:$viewValue | limitTo:5" <input type="text" class="form-control" aria-describedby="registry-name" uib-typeahead="image for image in $ctrl.availableImages | filter:$viewValue | limitTo:5"
ng-model="$ctrl.model.Image" name="image_name" placeholder="e.g. myImage:myTag" required> ng-model="$ctrl.model.Image" name="image_name" placeholder="e.g. myImage:myTag" required>
</div> </div>
@ -23,8 +13,8 @@
Registry Registry
</label> </label>
<div ng-class="$ctrl.inputClass" class="margin-sm-top"> <div ng-class="$ctrl.inputClass" class="margin-sm-top">
<select ng-options="registry as registry.Name for registry in $ctrl.availableRegistries" ng-model="$ctrl.model.Registry" id="image_registry" <select ng-options="registry as registry.Name for registry in $ctrl.availableRegistries track by registry.Name" ng-model="$ctrl.model.Registry" id="image_registry"
class="form-control"></select> selected-item-id="ctrl.selectedItemId" class="form-control"></select>
</div> </div>
</div> </div>
</div> </div>
@ -45,8 +35,20 @@
<div class="form-group" ng-show="$ctrl.form.image_name.$invalid"> <div class="form-group" ng-show="$ctrl.form.image_name.$invalid">
<div class="col-sm-12 small text-warning"> <div class="col-sm-12 small text-warning">
<div ng-messages="$ctrl.form.image_name.$error"> <div ng-messages="$ctrl.form.image_name.$error">
<p ng-message="required"><i class="fa fa-exclamation-triangle" aria-hidden="true"></i> Image name is required.</p> <p ng-message="required"><i class="fa fa-exclamation-triangle" aria-hidden="true"></i> Image name is required. <span ng-if="$ctrl.canPull">Tag must be specified otherwise Portainer will pull all tags associated to the image.</span></p>
</div> </div>
</div> </div>
</div> </div>
<!-- ! info message --> <!-- ! info message -->
<div class="form-group">
<div class="col-sm-12">
<p>
<a class="small interactive" ng-if="!$ctrl.model.UseRegistry" ng-click="$ctrl.model.UseRegistry = true;">
<i class="fa fa-database space-right" aria-hidden="true"></i> Use specific registry
</a>
<a class="small interactive" ng-if="$ctrl.model.UseRegistry" ng-click="$ctrl.model.UseRegistry = false;">
<i class="fa fa-globe space-right" aria-hidden="true"></i> Use public registry
</a>
</p>
</div>
</div>

View File

@ -21,7 +21,7 @@ class porImageRegistryController {
this.autoComplete ? this.ImageService.images() : [] this.autoComplete ? this.ImageService.images() : []
]); ]);
this.availableImages = this.ImageService.getUniqueTagListFromImages(availableImages); this.availableImages = this.ImageService.getUniqueTagListFromImages(availableImages);
this.availableRegistries = [dockerhub].concat(registries); this.availableRegistries = _.concat(dockerhub, registries);
const id = this.model.Registry.Id; const id = this.model.Registry.Id;
if (!id) { if (!id) {

View File

@ -29,20 +29,11 @@
<!-- image-and-registry --> <!-- image-and-registry -->
<por-image-registry <por-image-registry
model="formValues.RegistryModel" model="formValues.RegistryModel"
pull-warning="formValues.alwaysPull"
ng-if="formValues.RegistryModel.Registry" ng-if="formValues.RegistryModel.Registry"
auto-complete="true" 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 col-md-5"
></por-image-registry> ></por-image-registry>
<div class="form-group" ng-if="formValues.RegistryModel.UseRegistry">
<div class="col-sm-12">
<span class="small text-muted">Note: if you don't specify the tag in the image name, <span class="label label-default">latest</span> will be used.</span>
</div>
</div>
<div class="form-group" ng-if="formValues.alwaysPull && !formValues.RegistryModel.UseRegistry">
<div class="col-sm-12">
<span class="small text-muted"><i class="fa fa-exclamation-circle orange-icon" aria-hidden="true" style="margin-right: 2px;"></i> WARNING: if you don't specify the tag in the image name, all tags will be pulled for the image unless you don't ask Portainer to pull the image.</span>
</div>
</div>
<!-- !image-and-registry --> <!-- !image-and-registry -->
<!-- always-pull --> <!-- always-pull -->
<div class="form-group"> <div class="form-group">

View File

@ -17,21 +17,10 @@
<!-- image-and-registry --> <!-- image-and-registry -->
<por-image-registry <por-image-registry
model="formValues.RegistryModel" model="formValues.RegistryModel"
pull-warning="true"
label-class="col-sm-1" input-class="col-sm-11 col-md-5" label-class="col-sm-1" input-class="col-sm-11 col-md-5"
></por-image-registry> ></por-image-registry>
<!-- !image-and-registry --> <!-- !image-and-registry -->
<!-- tag-note -->
<div class="form-group" ng-if="formValues.RegistryModel.UseRegistry">
<div class="col-sm-12">
<span class="small text-muted">Note: if you don't specify the tag in the image name, <span class="label label-default">latest</span> will be used.</span>
</div>
</div>
<div class="form-group" ng-if="!formValues.RegistryModel.UseRegistry">
<div class="col-sm-12">
<span class="small text-muted"><i class="fa fa-exclamation-circle orange-icon" aria-hidden="true" style="margin-right: 2px;"></i> WARNING: if you don't specify the tag in the image name, all tags will be pulled for the image.</span>
</div>
</div>
<!-- !tag-note -->
<div ng-if="applicationState.endpoint.mode.agentProxy && applicationState.endpoint.mode.provider === 'DOCKER_SWARM_MODE'"> <div ng-if="applicationState.endpoint.mode.agentProxy && applicationState.endpoint.mode.provider === 'DOCKER_SWARM_MODE'">
<div class="col-sm-12 form-section-title"> <div class="col-sm-12 form-section-title">
Deployment Deployment

View File

@ -9,11 +9,6 @@
auto-complete="true" 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 col-md-5"
></por-image-registry> ></por-image-registry>
<div class="form-group">
<div class="col-sm-12">
<span class="small text-muted">Note: if you don't specify the tag in the image name, <span class="label label-default">latest</span> will be used.</span>
</div>
</div>
</form> </form>
</rd-widget-body> </rd-widget-body>
<rd-widget-body ng-if="isUpdating"> <rd-widget-body ng-if="isUpdating">

View File

@ -1,7 +1,6 @@
export function DockerHubViewModel(data) { export function DockerHubViewModel(data) {
this.Name = 'DockerHub'; this.Name = 'DockerHub';
this.URL = 'docker.io'; this.URL = '';
// this.URL = '';
this.Authentication = data.Authentication; this.Authentication = data.Authentication;
this.Username = data.Username; this.Username = data.Username;
this.Password = data.Password; this.Password = data.Password;

View File

@ -83,7 +83,7 @@ function RegistryServiceFactory($q, $async, Registries, DockerHubService, ImageH
service.retrievePorRegistryModelFromRepositoryWithRegistries = retrievePorRegistryModelFromRepositoryWithRegistries; service.retrievePorRegistryModelFromRepositoryWithRegistries = retrievePorRegistryModelFromRepositoryWithRegistries;
function retrievePorRegistryModelFromRepositoryWithRegistries(repository, registries) { function retrievePorRegistryModelFromRepositoryWithRegistries(repository, registries, dockerhub) {
const model = new PorImageRegistryModel(); const model = new PorImageRegistryModel();
const registry = _.find(registries, (reg) => _.includes(repository, reg.URL)); const registry = _.find(registries, (reg) => _.includes(repository, reg.URL));
if (registry) { if (registry) {
@ -93,6 +93,7 @@ function RegistryServiceFactory($q, $async, Registries, DockerHubService, ImageH
model.Image = image; model.Image = image;
} else { } else {
model.UseRegistry = false; model.UseRegistry = false;
model.Registry = dockerhub;
model.Image = repository; model.Image = repository;
} }
return model; return model;
@ -100,12 +101,11 @@ function RegistryServiceFactory($q, $async, Registries, DockerHubService, ImageH
async function retrievePorRegistryModelFromRepositoryAsync(repository) { async function retrievePorRegistryModelFromRepositoryAsync(repository) {
try { try {
const [registries, dockerhub] = await Promise.all([ let [registries, dockerhub] = await Promise.all([
service.registries(), service.registries(),
DockerHubService.dockerhub() DockerHubService.dockerhub()
]); ]);
registries.concat([dockerhub]); return retrievePorRegistryModelFromRepositoryWithRegistries(repository, registries, dockerhub);
return retrievePorRegistryModelFromRepositoryWithRegistries(repository, registries);
} catch (err) { } catch (err) {
throw { msg: 'Unable to retrieve the registry associated to the repository', err: err } throw { msg: 'Unable to retrieve the registry associated to the repository', err: err }
} }

View File

@ -19,10 +19,9 @@ function TemplateServiceFactory($q, Templates, TemplateHelper, RegistryService,
dockerhub: DockerHubService.dockerhub() dockerhub: DockerHubService.dockerhub()
}) })
.then(function success(data) { .then(function success(data) {
data.registries.concat([data.dockerhub]);
const templates = data.templates.map(function (item) { const templates = data.templates.map(function (item) {
const res = new TemplateViewModel(item); const res = new TemplateViewModel(item);
const registry = RegistryService.retrievePorRegistryModelFromRepositoryWithRegistries(res.RegistryModel.Registry, data.registries); const registry = RegistryService.retrievePorRegistryModelFromRepositoryWithRegistries(res.RegistryModel.Registry, data.registries, data.dockerhub);
registry.Image = res.RegistryModel.Image; registry.Image = res.RegistryModel.Image;
res.RegistryModel = registry; res.RegistryModel = registry;
return res; return res;