mirror of https://github.com/portainer/portainer
fix(app): refactor registry selector + registry auto select
parent
332aa4fbf5
commit
06c63899b2
|
@ -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': '@'
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 }
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue