mirror of https://github.com/portainer/portainer
Co-authored-by: Simon Meng <simon.meng@portainer.io>pull/4666/head
parent
dbb9a21384
commit
6d5877ca1c
|
@ -26,6 +26,8 @@ type registryCreatePayload struct {
|
||||||
Password string `example:"registry_password"`
|
Password string `example:"registry_password"`
|
||||||
// Gitlab specific details, required when type = 4
|
// Gitlab specific details, required when type = 4
|
||||||
Gitlab portainer.GitlabRegistryData
|
Gitlab portainer.GitlabRegistryData
|
||||||
|
// Quay specific details, required when type = 1
|
||||||
|
Quay portainer.QuayRegistryData
|
||||||
}
|
}
|
||||||
|
|
||||||
func (payload *registryCreatePayload) Validate(r *http.Request) error {
|
func (payload *registryCreatePayload) Validate(r *http.Request) error {
|
||||||
|
@ -74,6 +76,7 @@ func (handler *Handler) registryCreate(w http.ResponseWriter, r *http.Request) *
|
||||||
UserAccessPolicies: portainer.UserAccessPolicies{},
|
UserAccessPolicies: portainer.UserAccessPolicies{},
|
||||||
TeamAccessPolicies: portainer.TeamAccessPolicies{},
|
TeamAccessPolicies: portainer.TeamAccessPolicies{},
|
||||||
Gitlab: payload.Gitlab,
|
Gitlab: payload.Gitlab,
|
||||||
|
Quay: payload.Quay,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = handler.DataStore.Registry().CreateRegistry(registry)
|
err = handler.DataStore.Registry().CreateRegistry(registry)
|
||||||
|
|
|
@ -24,6 +24,7 @@ type registryUpdatePayload struct {
|
||||||
Password *string `example:"registry_password"`
|
Password *string `example:"registry_password"`
|
||||||
UserAccessPolicies portainer.UserAccessPolicies
|
UserAccessPolicies portainer.UserAccessPolicies
|
||||||
TeamAccessPolicies portainer.TeamAccessPolicies
|
TeamAccessPolicies portainer.TeamAccessPolicies
|
||||||
|
Quay *portainer.QuayRegistryData
|
||||||
}
|
}
|
||||||
|
|
||||||
func (payload *registryUpdatePayload) Validate(r *http.Request) error {
|
func (payload *registryUpdatePayload) Validate(r *http.Request) error {
|
||||||
|
@ -110,6 +111,10 @@ func (handler *Handler) registryUpdate(w http.ResponseWriter, r *http.Request) *
|
||||||
registry.TeamAccessPolicies = payload.TeamAccessPolicies
|
registry.TeamAccessPolicies = payload.TeamAccessPolicies
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if payload.Quay != nil {
|
||||||
|
registry.Quay = *payload.Quay
|
||||||
|
}
|
||||||
|
|
||||||
err = handler.DataStore.Registry().UpdateRegistry(registry.ID, registry)
|
err = handler.DataStore.Registry().UpdateRegistry(registry.ID, registry)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to persist registry changes inside the database", err}
|
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to persist registry changes inside the database", err}
|
||||||
|
|
|
@ -379,6 +379,12 @@ type (
|
||||||
ProjectPath string `json:"ProjectPath"`
|
ProjectPath string `json:"ProjectPath"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// QuayRegistryData represents data required for Quay registry to work
|
||||||
|
QuayRegistryData struct {
|
||||||
|
UseOrganisation bool `json:"UseOrganisation"`
|
||||||
|
OrganisationName string `json:"OrganisationName"`
|
||||||
|
}
|
||||||
|
|
||||||
// JobType represents a job type
|
// JobType represents a job type
|
||||||
JobType int
|
JobType int
|
||||||
|
|
||||||
|
@ -508,6 +514,7 @@ type (
|
||||||
Password string `json:"Password,omitempty" example:"registry_password"`
|
Password string `json:"Password,omitempty" example:"registry_password"`
|
||||||
ManagementConfiguration *RegistryManagementConfiguration `json:"ManagementConfiguration"`
|
ManagementConfiguration *RegistryManagementConfiguration `json:"ManagementConfiguration"`
|
||||||
Gitlab GitlabRegistryData `json:"Gitlab"`
|
Gitlab GitlabRegistryData `json:"Gitlab"`
|
||||||
|
Quay QuayRegistryData `json:"Quay"`
|
||||||
UserAccessPolicies UserAccessPolicies `json:"UserAccessPolicies"`
|
UserAccessPolicies UserAccessPolicies `json:"UserAccessPolicies"`
|
||||||
TeamAccessPolicies TeamAccessPolicies `json:"TeamAccessPolicies"`
|
TeamAccessPolicies TeamAccessPolicies `json:"TeamAccessPolicies"`
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,11 @@ angular.module('portainer.docker').factory('ImageHelper', [
|
||||||
if (registry.Registry.Type === RegistryTypes.GITLAB) {
|
if (registry.Registry.Type === RegistryTypes.GITLAB) {
|
||||||
const slash = _.startsWith(registry.Image, ':') ? '' : '/';
|
const slash = _.startsWith(registry.Image, ':') ? '' : '/';
|
||||||
fullImageName = registry.Registry.URL + '/' + registry.Registry.Gitlab.ProjectPath + slash + registry.Image;
|
fullImageName = registry.Registry.URL + '/' + registry.Registry.Gitlab.ProjectPath + slash + registry.Image;
|
||||||
|
}
|
||||||
|
if (registry.Registry.Type === RegistryTypes.QUAY) {
|
||||||
|
const name = registry.Registry.Quay.UseOrganisation ? registry.Registry.Quay.OrganisationName : registry.Registry.Username;
|
||||||
|
const url = registry.Registry.URL ? registry.Registry.URL + '/' : '';
|
||||||
|
fullImageName = url + name + '/' + registry.Image;
|
||||||
} else {
|
} else {
|
||||||
const url = registry.Registry.URL ? registry.Registry.URL + '/' : '';
|
const url = registry.Registry.URL ? registry.Registry.URL + '/' : '';
|
||||||
fullImageName = url + registry.Image;
|
fullImageName = url + registry.Image;
|
||||||
|
|
|
@ -32,6 +32,35 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- !credentials-password -->
|
<!-- !credentials-password -->
|
||||||
|
|
||||||
|
<!-- organisation-checkbox -->
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<label class="control-label text-left">
|
||||||
|
Use organisation registry
|
||||||
|
</label>
|
||||||
|
<label class="switch" style="margin-left: 20px;"> <input type="checkbox" ng-model="$ctrl.model.Quay.useOrganisation" /><i></i> </label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- !organisation-checkbox -->
|
||||||
|
<div ng-if="$ctrl.model.Quay.useOrganisation">
|
||||||
|
<!-- organisation_name -->
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="organisation_name" class="col-sm-3 col-lg-2 control-label text-left">Organisation name</label>
|
||||||
|
<div class="col-sm-9 col-lg-10">
|
||||||
|
<input type="text" class="form-control" id="organisation_name" name="organisation_name" ng-model="$ctrl.model.Quay.organisationName" required />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group" ng-show="registryFormQuay.organisation_name.$invalid">
|
||||||
|
<div class="col-sm-12 small text-warning">
|
||||||
|
<div ng-messages="registryFormQuay.organisation_name.$error">
|
||||||
|
<p ng-message="required"><i class="fa fa-exclamation-triangle" aria-hidden="true"></i> This field is required.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- !organisation_name -->
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- actions -->
|
<!-- actions -->
|
||||||
<div class="col-sm-12 form-section-title">
|
<div class="col-sm-12 form-section-title">
|
||||||
Actions
|
Actions
|
||||||
|
|
|
@ -15,6 +15,7 @@ export function RegistryViewModel(data) {
|
||||||
this.TeamAccessPolicies = data.TeamAccessPolicies;
|
this.TeamAccessPolicies = data.TeamAccessPolicies;
|
||||||
this.Checked = false;
|
this.Checked = false;
|
||||||
this.Gitlab = data.Gitlab;
|
this.Gitlab = data.Gitlab;
|
||||||
|
this.Quay = data.Quay;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function RegistryManagementConfigurationDefaultModel(registry) {
|
export function RegistryManagementConfigurationDefaultModel(registry) {
|
||||||
|
@ -64,4 +65,10 @@ export function RegistryCreateRequest(model) {
|
||||||
ProjectPath: model.Gitlab.ProjectPath,
|
ProjectPath: model.Gitlab.ProjectPath,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
if (model.Type === RegistryTypes.QUAY) {
|
||||||
|
this.Quay = {
|
||||||
|
useOrganisation: model.Quay.useOrganisation,
|
||||||
|
organisationName: model.Quay.organisationName,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,6 +96,9 @@ angular.module('portainer.app').factory('RegistryService', [
|
||||||
let url = reg.URL;
|
let url = reg.URL;
|
||||||
if (reg.Type === RegistryTypes.GITLAB) {
|
if (reg.Type === RegistryTypes.GITLAB) {
|
||||||
url = reg.URL + '/' + reg.Gitlab.ProjectPath;
|
url = reg.URL + '/' + reg.Gitlab.ProjectPath;
|
||||||
|
} else if (reg.Type === RegistryTypes.QUAY) {
|
||||||
|
const name = reg.Quay.UseOrganisation ? reg.Quay.OrganisationName : reg.Username;
|
||||||
|
url = reg.URL + '/' + name;
|
||||||
}
|
}
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,10 +28,17 @@ angular.module('portainer.app').controller('CreateRegistryController', [
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function useDefaultQuayConfiguration() {
|
||||||
|
$scope.model.Quay.useOrganisation = false;
|
||||||
|
$scope.model.Quay.organisationName = '';
|
||||||
|
}
|
||||||
|
|
||||||
function selectQuayRegistry() {
|
function selectQuayRegistry() {
|
||||||
$scope.model.Name = 'Quay';
|
$scope.model.Name = 'Quay';
|
||||||
$scope.model.URL = 'quay.io';
|
$scope.model.URL = 'quay.io';
|
||||||
$scope.model.Authentication = true;
|
$scope.model.Authentication = true;
|
||||||
|
$scope.model.Quay = {};
|
||||||
|
useDefaultQuayConfiguration();
|
||||||
}
|
}
|
||||||
|
|
||||||
function useDefaultGitlabConfiguration() {
|
function useDefaultGitlabConfiguration() {
|
||||||
|
|
|
@ -63,12 +63,36 @@
|
||||||
<!-- !credentials-password -->
|
<!-- !credentials-password -->
|
||||||
</div>
|
</div>
|
||||||
<!-- !authentication-credentials -->
|
<!-- !authentication-credentials -->
|
||||||
|
|
||||||
|
<div ng-if="registry.Type == RegistryTypes.QUAY">
|
||||||
|
<!-- organisation-checkbox -->
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<label class="control-label text-left">
|
||||||
|
Use organisation registry
|
||||||
|
</label>
|
||||||
|
<label class="switch" style="margin-left: 20px;"> <input type="checkbox" ng-model="registry.Quay.UseOrganisation" /><i></i> </label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- !organisation-checkbox -->
|
||||||
|
<div ng-if="registry.Quay.UseOrganisation">
|
||||||
|
<!-- organisation_name -->
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="organisation_name" class="col-sm-3 col-lg-2 control-label text-left">Organisation name</label>
|
||||||
|
<div class="col-sm-9 col-lg-10">
|
||||||
|
<input type="text" class="form-control" id="organisation_name" name="organisation_name" ng-model="registry.Quay.OrganisationName" required />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- !organisation_name -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="btn btn-primary btn-sm"
|
class="btn btn-primary btn-sm"
|
||||||
ng-disabled="state.actionInProgress || !registry.Name || !registry.URL"
|
ng-disabled="state.actionInProgress || !registry.Name || !registry.URL || (registry.Type == RegistryTypes.QUAY && registry.Quay.UseOrganisation && !registry.Quay.OrganisationName)"
|
||||||
ng-click="updateRegistry()"
|
ng-click="updateRegistry()"
|
||||||
button-spinner="state.actionInProgress"
|
button-spinner="state.actionInProgress"
|
||||||
>
|
>
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { RegistryTypes } from '@/portainer/models/registryTypes';
|
||||||
|
|
||||||
angular.module('portainer.app').controller('RegistryController', [
|
angular.module('portainer.app').controller('RegistryController', [
|
||||||
'$scope',
|
'$scope',
|
||||||
'$state',
|
'$state',
|
||||||
|
@ -14,6 +16,8 @@ angular.module('portainer.app').controller('RegistryController', [
|
||||||
Password: '',
|
Password: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.RegistryTypes = RegistryTypes;
|
||||||
|
|
||||||
$scope.updateRegistry = function () {
|
$scope.updateRegistry = function () {
|
||||||
var registry = $scope.registry;
|
var registry = $scope.registry;
|
||||||
registry.Password = $scope.formValues.Password;
|
registry.Password = $scope.formValues.Password;
|
||||||
|
|
Loading…
Reference in New Issue