fix(registry): #4371 cannot push to quay.io registry (#4868)

Co-authored-by: Simon Meng <simon.meng@portainer.io>
pull/4666/head
cong meng 2021-03-13 12:47:35 +13:00 committed by GitHub
parent dbb9a21384
commit 6d5877ca1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 95 additions and 1 deletions

View File

@ -26,6 +26,8 @@ type registryCreatePayload struct {
Password string `example:"registry_password"`
// Gitlab specific details, required when type = 4
Gitlab portainer.GitlabRegistryData
// Quay specific details, required when type = 1
Quay portainer.QuayRegistryData
}
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{},
TeamAccessPolicies: portainer.TeamAccessPolicies{},
Gitlab: payload.Gitlab,
Quay: payload.Quay,
}
err = handler.DataStore.Registry().CreateRegistry(registry)

View File

@ -24,6 +24,7 @@ type registryUpdatePayload struct {
Password *string `example:"registry_password"`
UserAccessPolicies portainer.UserAccessPolicies
TeamAccessPolicies portainer.TeamAccessPolicies
Quay *portainer.QuayRegistryData
}
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
}
if payload.Quay != nil {
registry.Quay = *payload.Quay
}
err = handler.DataStore.Registry().UpdateRegistry(registry.ID, registry)
if err != nil {
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to persist registry changes inside the database", err}

View File

@ -379,6 +379,12 @@ type (
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 int
@ -508,6 +514,7 @@ type (
Password string `json:"Password,omitempty" example:"registry_password"`
ManagementConfiguration *RegistryManagementConfiguration `json:"ManagementConfiguration"`
Gitlab GitlabRegistryData `json:"Gitlab"`
Quay QuayRegistryData `json:"Quay"`
UserAccessPolicies UserAccessPolicies `json:"UserAccessPolicies"`
TeamAccessPolicies TeamAccessPolicies `json:"TeamAccessPolicies"`

View File

@ -40,6 +40,11 @@ angular.module('portainer.docker').factory('ImageHelper', [
if (registry.Registry.Type === RegistryTypes.GITLAB) {
const slash = _.startsWith(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 {
const url = registry.Registry.URL ? registry.Registry.URL + '/' : '';
fullImageName = url + registry.Image;

View File

@ -32,6 +32,35 @@
</div>
</div>
<!-- !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 -->
<div class="col-sm-12 form-section-title">
Actions

View File

@ -15,6 +15,7 @@ export function RegistryViewModel(data) {
this.TeamAccessPolicies = data.TeamAccessPolicies;
this.Checked = false;
this.Gitlab = data.Gitlab;
this.Quay = data.Quay;
}
export function RegistryManagementConfigurationDefaultModel(registry) {
@ -64,4 +65,10 @@ export function RegistryCreateRequest(model) {
ProjectPath: model.Gitlab.ProjectPath,
};
}
if (model.Type === RegistryTypes.QUAY) {
this.Quay = {
useOrganisation: model.Quay.useOrganisation,
organisationName: model.Quay.organisationName,
};
}
}

View File

@ -96,6 +96,9 @@ angular.module('portainer.app').factory('RegistryService', [
let url = reg.URL;
if (reg.Type === RegistryTypes.GITLAB) {
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;
}

View File

@ -28,10 +28,17 @@ angular.module('portainer.app').controller('CreateRegistryController', [
},
};
function useDefaultQuayConfiguration() {
$scope.model.Quay.useOrganisation = false;
$scope.model.Quay.organisationName = '';
}
function selectQuayRegistry() {
$scope.model.Name = 'Quay';
$scope.model.URL = 'quay.io';
$scope.model.Authentication = true;
$scope.model.Quay = {};
useDefaultQuayConfiguration();
}
function useDefaultGitlabConfiguration() {

View File

@ -63,12 +63,36 @@
<!-- !credentials-password -->
</div>
<!-- !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="col-sm-12">
<button
type="button"
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()"
button-spinner="state.actionInProgress"
>

View File

@ -1,3 +1,5 @@
import { RegistryTypes } from '@/portainer/models/registryTypes';
angular.module('portainer.app').controller('RegistryController', [
'$scope',
'$state',
@ -14,6 +16,8 @@ angular.module('portainer.app').controller('RegistryController', [
Password: '',
};
$scope.RegistryTypes = RegistryTypes;
$scope.updateRegistry = function () {
var registry = $scope.registry;
registry.Password = $scope.formValues.Password;