Remove old setup page from main app
Change page for incomplete setup Remove old endpoints not in use
This commit is contained in:
parent
8eb7d73f22
commit
6afc00bf77
28 changed files with 100 additions and 4710 deletions
|
@ -1,8 +0,0 @@
|
|||
<div class="config-bool-field-element">
|
||||
<form name="fieldform" novalidate>
|
||||
<label>
|
||||
<input type="checkbox" ng-model="binding">
|
||||
<span ng-transclude/>
|
||||
</label>
|
||||
</form>
|
||||
</div>
|
|
@ -1,76 +0,0 @@
|
|||
<div class="config-certificates-field-element">
|
||||
<div class="resource-view" resource="certificatesResource" error-message="'Could not load certificates list'">
|
||||
<!-- File -->
|
||||
<div class="co-alert co-alert-warning" ng-if="certInfo.status == 'file'">
|
||||
<code>extra_ca_certs</code> is a single file and cannot be processed by this tool. If a valid and appended list of certificates, they will be installed on container startup.
|
||||
</div>
|
||||
|
||||
<div ng-if="certInfo.status != 'file'">
|
||||
<div class="description">
|
||||
<p>This section lists any custom or self-signed SSL certificates that are installed in the <span class="registry-name"></span> container on startup after being read from the <code>extra_ca_certs</code> directory in the configuration volume.
|
||||
</p>
|
||||
<p>
|
||||
Custom certificates are typically used in place of publicly signed certificates for corporate-internal services.
|
||||
</p>
|
||||
<p>Please <strong>make sure</strong> that all custom names used for downstream services (such as Clair) are listed in the certificates below.</p>
|
||||
</div>
|
||||
|
||||
<table class="config-table" style="margin-bottom: 20px;">
|
||||
<tr>
|
||||
<td>Upload certificates:</td>
|
||||
<td>
|
||||
<div class="file-upload-box"
|
||||
select-message="Select custom certificate to add to configuration. Must be in PEM format and end extension '.crt'"
|
||||
files-selected="handleCertsSelected(files, callback)"
|
||||
reset="resetUpload"
|
||||
extensions="['.crt']"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table class="co-table">
|
||||
<thead>
|
||||
<td>Certificate Filename</td>
|
||||
<td>Status</td>
|
||||
<td>Names Handled</td>
|
||||
<td class="options-col"></td>
|
||||
</thead>
|
||||
<tr ng-repeat="certificate in certInfo.certs" ng-if="!certsUploading">
|
||||
<td>{{ certificate.path }}</td>
|
||||
<td class="cert-status">
|
||||
<div ng-if="certificate.error" class="red">
|
||||
<i class="fa fa-exclamation-circle"></i>
|
||||
Error: {{ certificate.error }}
|
||||
</div>
|
||||
<div ng-if="certificate.expired" class="orange">
|
||||
<i class="fa fa-exclamation-triangle"></i>
|
||||
Certificate is expired
|
||||
</div>
|
||||
<div ng-if="!certificate.error && !certificate.expired" class="green">
|
||||
<i class="fa fa-check-circle"></i>
|
||||
Certificate is valid
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="empty" ng-if="!certificate.names">(None)</div>
|
||||
<a class="dns-name" ng-href="http://{{ name }}" ng-repeat="name in certificate.names" ng-safenewtab>{{ name }}</a>
|
||||
</td>
|
||||
<td class="options-col">
|
||||
<span class="cor-options-menu">
|
||||
<span class="cor-option" option-click="deleteCert(certificate.path)">
|
||||
<i class="fa fa-times"></i> Delete Certificate
|
||||
</span>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div ng-if="certsUploading" style="margin-top: 20px; text-align: center;">
|
||||
<div class="cor-loader-inline"></div>
|
||||
Uploading, validating and updating certificate(s)
|
||||
</div>
|
||||
<div class="empty" ng-if="!certInfo.certs.length && !certsUploading" style="margin-top: 20px;">
|
||||
<div class="empty-primary-msg">No custom certificates found.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,46 +0,0 @@
|
|||
<div class="config-contact-field-element">
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-default dropdown-toggle" type="button" data-toggle="dropdown">
|
||||
<span ng-switch="kind">
|
||||
<span ng-switch-when="mailto"><i class="fa fa-envelope"></i>E-mail</span>
|
||||
<span ng-switch-when="irc"><i class="fa fa-comment"></i>IRC</span>
|
||||
<span ng-switch-when="tel"><i class="fa fa-phone"></i>Phone</span>
|
||||
<span ng-switch-default><i class="fa fa-ticket"></i>URL</span>
|
||||
</span>
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li role="presentation">
|
||||
<a role="menuitem" tabindex="-1" ng-click="kind = 'mailto'">
|
||||
<i class="fa fa-envelope"></i> E-mail
|
||||
</a>
|
||||
</li>
|
||||
<li role="presentation">
|
||||
<a role="menuitem" tabindex="-1" ng-click="kind = 'irc'">
|
||||
<i class="fa fa-comment"></i> IRC
|
||||
</a>
|
||||
</li>
|
||||
<li role="presentation">
|
||||
<a role="menuitem" tabindex="-1" ng-click="kind = 'tel'">
|
||||
<i class="fa fa-phone"></i> Telephone
|
||||
</a>
|
||||
</li>
|
||||
<li role="presentation">
|
||||
<a role="menuitem" tabindex="-1" ng-click="kind = 'http'">
|
||||
<i class="fa fa-ticket"></i> URL
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<form>
|
||||
<input class="form-control" placeholder="{{ getPlaceholder(kind) }}" ng-model="value">
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
|
@ -1,4 +0,0 @@
|
|||
<div class="config-contacts-field-element">
|
||||
<div class="config-contact-field" binding="item.value" ng-repeat="item in items">
|
||||
</div>
|
||||
</div>
|
|
@ -1,13 +0,0 @@
|
|||
<div class="config-file-field-element">
|
||||
<span ng-show="uploadProgress == null">
|
||||
<span ng-if="hasFile">
|
||||
<code>/conf/stack/{{ filename }}</code>
|
||||
<span style="margin-left: 20px; display: inline-block;">Select a replacement file:</span>
|
||||
</span>
|
||||
<span class="nofile" ng-if="!hasFile && skipCheckFile != 'true'">Please select a file to upload as <b>{{ filename }}</b>: </span>
|
||||
<input type="file" ng-file-select="onFileSelect($files)">
|
||||
</span>
|
||||
<span ng-show="uploadProgress != null">
|
||||
Uploading file as <strong>{{ filename }}</strong>... {{ uploadProgress }}%
|
||||
</span>
|
||||
</div>
|
|
@ -1,17 +0,0 @@
|
|||
<div class="config-list-field-element">
|
||||
<ul ng-show="binding && binding.length">
|
||||
<li class="item" ng-repeat="item in binding">
|
||||
<span class="item-title">{{ item }}</span>
|
||||
<span class="item-delete">
|
||||
<a ng-click="removeItem(item)">Remove</a>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
<span class="empty" ng-if="!binding || binding.length == 0">No {{ itemTitle }}s defined</span>
|
||||
<form class="form-control-container" ng-submit="addItem()">
|
||||
<input type="text" class="form-control" placeholder="{{ placeholder }}"
|
||||
ng-pattern="getRegexp(itemPattern)"
|
||||
ng-model="newItemName" style="display: inline-block">
|
||||
<button class="btn btn-default" style="display: inline-block">Add</button>
|
||||
</form>
|
||||
</div>
|
|
@ -1,20 +0,0 @@
|
|||
<div class="config-map-field-element">
|
||||
<table class="table" ng-show="hasValues(binding)">
|
||||
<tr class="item" ng-repeat="(key, value) in binding">
|
||||
<td class="item-title">{{ key }}</td>
|
||||
<td class="item-value">{{ value }}</td>
|
||||
<td class="item-delete">
|
||||
<a ng-click="removeKey(key)">Remove</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<span class="empty" ng-if="!hasValues(binding)">No entries defined</span>
|
||||
<form class="form-control-container" ng-submit="addEntry()">
|
||||
Add Key-Value:
|
||||
<select ng-model="newKey">
|
||||
<option ng-repeat="key in keys" value="{{ key }}">{{ key }}</option>
|
||||
</select>
|
||||
<input type="text" class="form-control" placeholder="Value" ng-model="newValue">
|
||||
<button class="btn btn-default" style="display: inline-block">Add Entry</button>
|
||||
</form>
|
||||
</div>
|
|
@ -1,6 +0,0 @@
|
|||
<div class="config-numeric-field-element">
|
||||
<form name="fieldform" novalidate>
|
||||
<input type="number" class="form-control" placeholder="{{ placeholder || '' }}"
|
||||
ng-model="bindinginternal" ng-trim="false" ng-minlength="1" required>
|
||||
</form>
|
||||
</div>
|
|
@ -1 +0,0 @@
|
|||
<div class="config-parsed-field-element"></div>
|
|
@ -1,29 +0,0 @@
|
|||
<div class="config-service-key-field-element">
|
||||
<!-- Loading -->
|
||||
<div class="cor-loader" ng-if="loading"></div>
|
||||
|
||||
<!-- Loading error -->
|
||||
<div class="co-alert co-alert-warning" ng-if="loadError">
|
||||
Could not load service keys
|
||||
</div>
|
||||
|
||||
<!-- Key config -->
|
||||
<div ng-show="!loading && !loadError">
|
||||
<div ng-show="hasValidKey">
|
||||
<i class="fa fa-check"></i>
|
||||
Valid key for service <code>{{ serviceName }}</code> exists
|
||||
</div>
|
||||
<div ng-show="!hasValidKey">
|
||||
No valid key found for service <code>{{ serviceName }}</code>
|
||||
<a class="co-modify-link" ng-click="showRequestServiceKey()">Create Key</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Note: This field is a hidden text field that binds to a model that is set to non-empty
|
||||
when there is a valid key. This allows us to use the existing Angular form validation
|
||||
code.
|
||||
-->
|
||||
<input type="text" ng-model="hasValidKeyStr" ng-required="true" style="position: absolute; top: 0px; left: 0px; visibility: hidden; width: 0px; height: 0px;">
|
||||
|
||||
<div class="request-service-key-dialog" request-key-info="requestKeyInfo" key-created="handleKeyCreated(key)"></div>
|
||||
</div>
|
File diff suppressed because it is too large
Load diff
|
@ -1,10 +0,0 @@
|
|||
<div class="config-string-field-element">
|
||||
<form name="fieldform" novalidate>
|
||||
<input type="text" class="form-control" placeholder="{{ placeholder || '' }}"
|
||||
ng-model="binding" ng-trim="false" ng-minlength="1"
|
||||
ng-pattern="getRegexp(pattern)" ng-required="!isOptional">
|
||||
<div class="alert alert-danger" ng-show="errorMessage">
|
||||
{{ errorMessage }}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
|
@ -1,6 +0,0 @@
|
|||
<div class="config-string-list-field-element">
|
||||
<form name="fieldform" novalidate>
|
||||
<input type="text" class="form-control" placeholder="{{ placeholder || '' }}"
|
||||
ng-model="internalBinding" ng-trim="true" ng-minlength="1" ng-required="!isOptional">
|
||||
</form>
|
||||
</div>
|
|
@ -1,10 +0,0 @@
|
|||
<div class="config-variable-field-element">
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-default"
|
||||
ng-repeat="section in sections"
|
||||
ng-click="setSection(section)"
|
||||
ng-class="section == currentSection ? 'active' : ''">{{ section.title }}</button>
|
||||
</div>
|
||||
|
||||
<span ng-transclude></span>
|
||||
</div>
|
|
@ -1,137 +0,0 @@
|
|||
<div class="request-service-key-dialog-element">
|
||||
<!-- Modal message dialog -->
|
||||
<div class="co-dialog modal fade">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" ng-show="!working">×</button>
|
||||
<h4 class="modal-title">Create key for service {{ requestKeyInfo.service }}</h4>
|
||||
</div>
|
||||
|
||||
<div class="modal-body" ng-show="working">
|
||||
<div class="cor-loader"></div>
|
||||
</div>
|
||||
|
||||
<div class="modal-body" ng-show="!working">
|
||||
<!-- Step 0 -->
|
||||
<div ng-show="step == 0">
|
||||
<table class="co-option-table">
|
||||
<tr>
|
||||
<td><input type="radio" id="automaticKey" ng-model="requestKind" value="automatic"></td>
|
||||
<td>
|
||||
<label for="automaticKey">Have the service provide a key</label>
|
||||
<div class="help-text">Recommended for <code>{{ requestKeyInfo.service }}</code> installations where the single instance is setup now.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input type="radio" id="presharedKey" ng-model="requestKind" value="preshared"></td>
|
||||
<td>
|
||||
<label for="presharedKey">Generate shared key</label>
|
||||
<div class="help-text">Recommended for <code>{{ requestKeyInfo.service }}</code> installations where the instances are dynamically started.</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Step 1 (automatic) -->
|
||||
<div ng-show="step == 1 && requestKind == 'automatic'" style="text-align: center">
|
||||
<div style="margin-top: 20px;">
|
||||
Please start the <code>{{ requestKeyInfo.service }}</code> service now, configured for <a href="https://github.com/coreos/jwtproxy#autogenerated-private-key" ng-safenewtab>autogenerated private key</a>. The key approval process will continue automatically once the service connects to Quay.
|
||||
</div>
|
||||
<div style="margin-top: 20px;">
|
||||
Waiting for service to connect
|
||||
</div>
|
||||
<div style="margin-top: 10px; margin-bottom: 20px;">
|
||||
<div class="cor-loader-inline"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 (automatic) -->
|
||||
<div ng-show="step == 2 && requestKind == 'automatic'" style="text-align: center">
|
||||
A key for service <code>{{ requestKeyInfo.service }}</code> has been automatically generated, approved and saved in the service's keystore.
|
||||
</div>
|
||||
|
||||
<!-- Step 1 (generate) -->
|
||||
<div ng-show="step == 1 && requestKind == 'preshared'">
|
||||
<form name="createForm" ng-submit="createPresharedKey()">
|
||||
<table class="co-form-table">
|
||||
<tr>
|
||||
<td><label for="create-key-name">Key Name:</label></td>
|
||||
<td>
|
||||
<input class="form-control" name="create-key-name" type="text" ng-model="preshared.name" placeholder="Friendly Key Name">
|
||||
<span class="co-help-text">
|
||||
A friendly name for the key for later reference.
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="create-key-expiration">Expiration date (optional):</label></td>
|
||||
<td>
|
||||
<span class="datetime-picker" datetime="preshared.expiration"></span>
|
||||
<span class="co-help-text">
|
||||
The date and time that the key expires. If left blank, the key will never expire.
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="create-key-notes">Approval Notes (optional):</label></td>
|
||||
<td>
|
||||
<markdown-input content="preshared.notes"
|
||||
can-write="true"
|
||||
(content-changed)="updateNotes($event.content)"
|
||||
field-title="notes"></markdown-input>
|
||||
<span class="co-help-text">
|
||||
Optional notes for additional human-readable information about why the key was created.
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 (generate) -->
|
||||
<div ng-show="step == 2 && requestKind == 'preshared'">
|
||||
<div class="co-alert co-alert-warning">
|
||||
The following key has been generated for service <code>{{ requestKeyInfo.service }}</code>.
|
||||
<br><br>
|
||||
Please copy the key's ID and copy/download the key's private contents and place it in the directory with the service's configuration.
|
||||
<br><br>
|
||||
<strong>Once this dialog is closed this private key will not be accessible anywhere else!</strong>
|
||||
</div>
|
||||
|
||||
<label>Key ID:</label>
|
||||
<div class="copy-box" value="createdKey.kid"></div>
|
||||
|
||||
<label>Private Key (PEM):</label>
|
||||
<textarea class="key-display form-control" onclick="this.focus();this.select()" readonly>{{ createdKey.private_key }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer" ng-show="!working">
|
||||
<button type="button" class="btn btn-primary" ng-show="step == 1 && requestKind == 'preshared'"
|
||||
ng-disabled="createForm.$invalid"
|
||||
ng-click="createPresharedKey()">
|
||||
Generate Key
|
||||
</button>
|
||||
|
||||
<button type="button" class="btn btn-primary" ng-show="step == 0 && requestKind == 'preshared'"
|
||||
ng-click="showGenerate()">
|
||||
Continue
|
||||
</button>
|
||||
|
||||
<button type="button" class="btn btn-primary" ng-show="step == 0 && requestKind == 'automatic'"
|
||||
ng-click="startApproval()">
|
||||
Start Approval
|
||||
</button>
|
||||
|
||||
<button type="button" class="btn btn-primary" ng-click="downloadPrivateKey(createdKey)" ng-if="createdKey && isDownloadSupported()">
|
||||
<i class="fa fa-download"></i> Download Private Key
|
||||
</button>
|
||||
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal" ng-show="step == 2">Close</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal" ng-show="step != 2">Cancel</button>
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
||||
</div>
|
||||
</div>
|
File diff suppressed because it is too large
Load diff
|
@ -318,39 +318,6 @@ angular.module("core-ui", [])
|
|||
return directiveDefinitionObject;
|
||||
})
|
||||
|
||||
.directive('corStepBar', function() {
|
||||
var directiveDefinitionObject = {
|
||||
priority: 4,
|
||||
templateUrl: '/static/directives/cor-step-bar.html',
|
||||
replace: true,
|
||||
transclude: true,
|
||||
restrict: 'C',
|
||||
scope: {
|
||||
'progress': '=progress'
|
||||
},
|
||||
controller: function($rootScope, $scope, $element) {
|
||||
$scope.$watch('progress', function(progress) {
|
||||
if (!progress) { return; }
|
||||
|
||||
var index = 0;
|
||||
for (var i = 0; i < progress.length; ++i) {
|
||||
if (progress[i]) {
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
|
||||
$element.find('.transclude').children('.co-step-element').each(function(i, elem) {
|
||||
$(elem).removeClass('active');
|
||||
if (i <= index) {
|
||||
$(elem).addClass('active');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
return directiveDefinitionObject;
|
||||
})
|
||||
|
||||
.directive('corCheckableMenu', function() {
|
||||
var directiveDefinitionObject = {
|
||||
priority: 1,
|
||||
|
|
|
@ -1,124 +0,0 @@
|
|||
/**
|
||||
* An element which displays a dialog for requesting or creating a service key.
|
||||
*/
|
||||
angular.module('quay').directive('requestServiceKeyDialog', function () {
|
||||
var directiveDefinitionObject = {
|
||||
priority: 0,
|
||||
templateUrl: '/static/directives/request-service-key-dialog.html',
|
||||
replace: false,
|
||||
transclude: true,
|
||||
restrict: 'C',
|
||||
scope: {
|
||||
'requestKeyInfo': '=requestKeyInfo',
|
||||
'keyCreated': '&keyCreated'
|
||||
},
|
||||
controller: function($scope, $element, $timeout, ApiService) {
|
||||
var handleNewKey = function(key) {
|
||||
var data = {
|
||||
'notes': 'Approved during setup of service ' + key.service
|
||||
};
|
||||
|
||||
var params = {
|
||||
'kid': key.kid
|
||||
};
|
||||
|
||||
ApiService.approveServiceKey(data, params).then(function(resp) {
|
||||
$scope.keyCreated({'key': key});
|
||||
$scope.step = 2;
|
||||
}, ApiService.errorDisplay('Could not approve service key'));
|
||||
};
|
||||
|
||||
var checkKeys = function() {
|
||||
var isShown = ($element.find('.modal').data('bs.modal') || {}).isShown;
|
||||
if (!isShown) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: filter by service.
|
||||
ApiService.listServiceKeys().then(function(resp) {
|
||||
var keys = resp['keys'];
|
||||
for (var i = 0; i < keys.length; ++i) {
|
||||
var key = keys[i];
|
||||
if (key.service == $scope.requestKeyInfo.service && !key.approval && key.rotation_duration) {
|
||||
handleNewKey(key);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$timeout(checkKeys, 1000);
|
||||
}, ApiService.errorDisplay('Could not list service keys'));
|
||||
};
|
||||
|
||||
$scope.show = function() {
|
||||
$scope.working = false;
|
||||
$scope.step = 0;
|
||||
$scope.requestKind = null;
|
||||
$scope.preshared = {
|
||||
'name': $scope.requestKeyInfo.service + ' Service Key',
|
||||
'notes': 'Created during setup for service `' + $scope.requestKeyInfo.service + '`'
|
||||
};
|
||||
|
||||
$element.find('.modal').modal({});
|
||||
};
|
||||
|
||||
$scope.hide = function() {
|
||||
$scope.loading = false;
|
||||
$element.find('.modal').modal('hide');
|
||||
};
|
||||
|
||||
$scope.showGenerate = function() {
|
||||
$scope.step = 1;
|
||||
};
|
||||
|
||||
$scope.startApproval = function() {
|
||||
$scope.step = 1;
|
||||
checkKeys();
|
||||
};
|
||||
|
||||
$scope.isDownloadSupported = function() {
|
||||
var isSafari = /^((?!chrome).)*safari/i.test(navigator.userAgent);
|
||||
if (isSafari) {
|
||||
// Doesn't work properly in Safari, sadly.
|
||||
return false;
|
||||
}
|
||||
|
||||
try { return !!new Blob(); } catch(e) {}
|
||||
return false;
|
||||
};
|
||||
|
||||
$scope.downloadPrivateKey = function(key) {
|
||||
var blob = new Blob([key.private_key]);
|
||||
FileSaver.saveAs(blob, key.service + '.pem');
|
||||
};
|
||||
|
||||
$scope.createPresharedKey = function() {
|
||||
$scope.working = true;
|
||||
|
||||
var data = {
|
||||
'name': $scope.preshared.name,
|
||||
'service': $scope.requestKeyInfo.service,
|
||||
'expiration': $scope.preshared.expiration || null,
|
||||
'notes': $scope.preshared.notes
|
||||
};
|
||||
|
||||
ApiService.createServiceKey(data).then(function(resp) {
|
||||
$scope.working = false;
|
||||
$scope.step = 2;
|
||||
$scope.createdKey = resp;
|
||||
$scope.keyCreated({'key': resp});
|
||||
}, ApiService.errorDisplay('Could not create service key'));
|
||||
};
|
||||
|
||||
$scope.updateNotes = function(content) {
|
||||
$scope.preshared.notes = content;
|
||||
};
|
||||
|
||||
$scope.$watch('requestKeyInfo', function(info) {
|
||||
if (info && info.service) {
|
||||
$scope.show();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
return directiveDefinitionObject;
|
||||
});
|
74
static/js/pages/incomplete-setup.js
Normal file
74
static/js/pages/incomplete-setup.js
Normal file
|
@ -0,0 +1,74 @@
|
|||
(function() {
|
||||
/**
|
||||
* The Incomplete Setup page provides information to the user about what's wrong with the current configuration
|
||||
*/
|
||||
angular.module('quayPages').config(['pages', function(pages) {
|
||||
pages.create('incomplete-setup', 'incomplete-setup.html', IncompleteSetupCtrl,
|
||||
{
|
||||
'newLayout': true,
|
||||
'title': 'Quay Enterprise Setup Incomplete'
|
||||
})
|
||||
}]);
|
||||
|
||||
function IncompleteSetupCtrl($scope, $timeout, ApiService, Features, UserService, ContainerService, CoreDialog) {
|
||||
if (!Features.SUPER_USERS) {
|
||||
return;
|
||||
}
|
||||
|
||||
$scope.States = {
|
||||
// Loading the state of the product.
|
||||
'LOADING': 'loading',
|
||||
|
||||
// The configuration directory is missing.
|
||||
'MISSING_CONFIG_DIR': 'missing-config-dir',
|
||||
|
||||
// The config.yaml exists but it is invalid.
|
||||
'INVALID_CONFIG': 'config-invalid',
|
||||
};
|
||||
|
||||
$scope.currentStep = $scope.States.LOADING;
|
||||
|
||||
$scope.$watch('currentStep', function(currentStep) {
|
||||
switch (currentStep) {
|
||||
case $scope.States.MISSING_CONFIG_DIR:
|
||||
$scope.showMissingConfigDialog();
|
||||
break;
|
||||
|
||||
case $scope.States.INVALID_CONFIG:
|
||||
$scope.showInvalidConfigDialog();
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
$scope.showInvalidConfigDialog = function() {
|
||||
var message = "The <code>config.yaml</code> file found in <code>conf/stack</code> could not be parsed."
|
||||
var title = "Invalid configuration file";
|
||||
CoreDialog.fatal(title, message);
|
||||
};
|
||||
|
||||
|
||||
$scope.showMissingConfigDialog = function() {
|
||||
var message = "It looks like Quay was not mounted with a configuration volume. The volume should be " +
|
||||
"mounted into the container at <code>/conf/stack</code>. " +
|
||||
"<br>If you have a tarball, please ensure you untar it into a directory and re-run this container with: " +
|
||||
"<br><br><pre>docker run -v /path/to/config:/conf/stack</pre>" +
|
||||
"<br>If you haven't configured your Quay instance, please run the container with: " +
|
||||
"<br><br><pre>docker run <name-of-image> config </pre>" +
|
||||
"For more information, " +
|
||||
"<a href='https://coreos.com/docs/enterprise-registry/initial-setup/'>" +
|
||||
"Read the Setup Guide</a>";
|
||||
|
||||
var title = "Missing configuration volume";
|
||||
CoreDialog.fatal(title, message);
|
||||
};
|
||||
|
||||
$scope.checkStatus = function() {
|
||||
ContainerService.checkStatus(function(resp) {
|
||||
$scope.currentStep = resp['status'];
|
||||
}, $scope.currentConfig);
|
||||
};
|
||||
|
||||
// Load the initial status.
|
||||
$scope.checkStatus();
|
||||
};
|
||||
})();
|
|
@ -15,7 +15,7 @@
|
|||
$scope.userRegistered = false;
|
||||
|
||||
if (!Config['SETUP_COMPLETE'] && !Features.BILLING) {
|
||||
$location.path('/setup');
|
||||
$location.path('/incomplete-setup');
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,325 +0,0 @@
|
|||
import * as URI from 'urijs';
|
||||
|
||||
(function() {
|
||||
/**
|
||||
* The Setup page provides a nice GUI walkthrough experience for setting up Quay Enterprise.
|
||||
*/
|
||||
angular.module('quayPages').config(['pages', function(pages) {
|
||||
pages.create('setup', 'setup.html', SetupCtrl,
|
||||
{
|
||||
'newLayout': true,
|
||||
'title': 'Quay Enterprise Setup'
|
||||
})
|
||||
}]);
|
||||
|
||||
function SetupCtrl($scope, $timeout, ApiService, Features, UserService, ContainerService, CoreDialog) {
|
||||
if (!Features.SUPER_USERS) {
|
||||
return;
|
||||
}
|
||||
|
||||
$scope.HOSTNAME_REGEX = '^[a-zA-Z-0-9_\.\-]+(:[0-9]+)?$';
|
||||
|
||||
$scope.validateHostname = function(hostname) {
|
||||
if (hostname.indexOf('127.0.0.1') == 0 || hostname.indexOf('localhost') == 0) {
|
||||
return 'Please specify a non-localhost hostname. "localhost" will refer to the container, not your machine.'
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
// Note: The values of the enumeration are important for isStepFamily. For example,
|
||||
// *all* states under the "configuring db" family must start with "config-db".
|
||||
$scope.States = {
|
||||
// Loading the state of the product.
|
||||
'LOADING': 'loading',
|
||||
|
||||
// The configuration directory is missing.
|
||||
'MISSING_CONFIG_DIR': 'missing-config-dir',
|
||||
|
||||
// The config.yaml exists but it is invalid.
|
||||
'INVALID_CONFIG': 'config-invalid',
|
||||
|
||||
// DB is being configured.
|
||||
'CONFIG_DB': 'config-db',
|
||||
|
||||
// DB information is being validated.
|
||||
'VALIDATING_DB': 'config-db-validating',
|
||||
|
||||
// DB information is being saved to the config.
|
||||
'SAVING_DB': 'config-db-saving',
|
||||
|
||||
// A validation error occurred with the database.
|
||||
'DB_ERROR': 'config-db-error',
|
||||
|
||||
// Database is being setup.
|
||||
'DB_SETUP': 'setup-db',
|
||||
|
||||
// Database setup has succeeded.
|
||||
'DB_SETUP_SUCCESS': 'setup-db-success',
|
||||
|
||||
// An error occurred when setting up the database.
|
||||
'DB_SETUP_ERROR': 'setup-db-error',
|
||||
|
||||
// The container is being restarted for the database changes.
|
||||
'DB_RESTARTING': 'setup-db-restarting',
|
||||
|
||||
// A superuser is being configured.
|
||||
'CREATE_SUPERUSER': 'create-superuser',
|
||||
|
||||
// The superuser is being created.
|
||||
'CREATING_SUPERUSER': 'create-superuser-creating',
|
||||
|
||||
// An error occurred when setting up the superuser.
|
||||
'SUPERUSER_ERROR': 'create-superuser-error',
|
||||
|
||||
// The superuser was created successfully.
|
||||
'SUPERUSER_CREATED': 'create-superuser-created',
|
||||
|
||||
// General configuration is being setup.
|
||||
'CONFIG': 'config',
|
||||
|
||||
// The configuration is fully valid.
|
||||
'VALID_CONFIG': 'valid-config',
|
||||
|
||||
// The container is being restarted for the configuration changes.
|
||||
'CONFIG_RESTARTING': 'config-restarting',
|
||||
|
||||
// The product is ready for use.
|
||||
'READY': 'ready'
|
||||
}
|
||||
|
||||
$scope.csrf_token = window.__token;
|
||||
$scope.currentStep = $scope.States.LOADING;
|
||||
$scope.errors = {};
|
||||
$scope.stepProgress = [];
|
||||
$scope.hasSSL = false;
|
||||
$scope.hostname = null;
|
||||
$scope.currentConfig = null;
|
||||
|
||||
$scope.currentState = {
|
||||
'hasDatabaseSSLCert': false
|
||||
};
|
||||
|
||||
$scope.$watch('currentStep', function(currentStep) {
|
||||
$scope.stepProgress = $scope.getProgress(currentStep);
|
||||
|
||||
switch (currentStep) {
|
||||
case $scope.States.CONFIG:
|
||||
$('#setupModal').modal('hide');
|
||||
break;
|
||||
|
||||
case $scope.States.MISSING_CONFIG_DIR:
|
||||
$scope.showMissingConfigDialog();
|
||||
break;
|
||||
|
||||
case $scope.States.INVALID_CONFIG:
|
||||
$scope.showInvalidConfigDialog();
|
||||
break;
|
||||
|
||||
case $scope.States.DB_SETUP:
|
||||
$scope.performDatabaseSetup();
|
||||
// Fall-through.
|
||||
|
||||
case $scope.States.CREATE_SUPERUSER:
|
||||
case $scope.States.DB_RESTARTING:
|
||||
case $scope.States.CONFIG_DB:
|
||||
case $scope.States.VALID_CONFIG:
|
||||
case $scope.States.READY:
|
||||
$('#setupModal').modal({
|
||||
keyboard: false,
|
||||
backdrop: 'static'
|
||||
});
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
$scope.restartContainer = function(state) {
|
||||
$scope.currentStep = state;
|
||||
ContainerService.restartContainer(function() {
|
||||
$scope.checkStatus()
|
||||
});
|
||||
};
|
||||
|
||||
$scope.showSuperuserPanel = function() {
|
||||
$('#setupModal').modal('hide');
|
||||
var prefix = $scope.hasSSL ? 'https' : 'http';
|
||||
var hostname = $scope.hostname;
|
||||
if (!hostname) {
|
||||
hostname = document.location.hostname;
|
||||
if (document.location.port) {
|
||||
hostname = hostname + ':' + document.location.port;
|
||||
}
|
||||
}
|
||||
|
||||
window.location = prefix + '://' + hostname + '/superuser';
|
||||
};
|
||||
|
||||
$scope.configurationSaved = function(config) {
|
||||
$scope.hasSSL = config['PREFERRED_URL_SCHEME'] == 'https';
|
||||
$scope.hostname = config['SERVER_HOSTNAME'];
|
||||
$scope.currentConfig = config;
|
||||
|
||||
$scope.currentStep = $scope.States.VALID_CONFIG;
|
||||
};
|
||||
|
||||
$scope.getProgress = function(step) {
|
||||
var isStep = $scope.isStep;
|
||||
var isStepFamily = $scope.isStepFamily;
|
||||
var States = $scope.States;
|
||||
|
||||
return [
|
||||
isStepFamily(step, States.CONFIG_DB),
|
||||
isStepFamily(step, States.DB_SETUP),
|
||||
isStep(step, States.DB_RESTARTING),
|
||||
isStepFamily(step, States.CREATE_SUPERUSER),
|
||||
isStep(step, States.CONFIG),
|
||||
isStep(step, States.VALID_CONFIG),
|
||||
isStep(step, States.CONFIG_RESTARTING),
|
||||
isStep(step, States.READY)
|
||||
];
|
||||
};
|
||||
|
||||
$scope.isStepFamily = function(step, family) {
|
||||
if (!step) { return false; }
|
||||
return step.indexOf(family) == 0;
|
||||
};
|
||||
|
||||
$scope.isStep = function(step) {
|
||||
for (var i = 1; i < arguments.length; ++i) {
|
||||
if (arguments[i] == step) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
$scope.beginSetup = function() {
|
||||
$scope.currentStep = $scope.States.CONFIG_DB;
|
||||
};
|
||||
|
||||
$scope.showInvalidConfigDialog = function() {
|
||||
var message = "The <code>config.yaml</code> file found in <code>conf/stack</code> could not be parsed."
|
||||
var title = "Invalid configuration file";
|
||||
CoreDialog.fatal(title, message);
|
||||
};
|
||||
|
||||
|
||||
$scope.showMissingConfigDialog = function() {
|
||||
var message = "It looks like Quay was not mounted with a configuration volume. The volume should be " +
|
||||
"mounted into the container at <code>/conf/stack</code>. " +
|
||||
"<br>If you have a tarball, please ensure you untar it into a directory and re-run this container with: " +
|
||||
"<br><br><pre>docker run -v /path/to/config:/conf/stack</pre>" +
|
||||
"<br>If you haven't configured your Quay instance, please run the container with: " +
|
||||
"<br><br><pre>docker run <name-of-image> config </pre>" +
|
||||
"For more information, " +
|
||||
"<a href='https://coreos.com/docs/enterprise-registry/initial-setup/'>" +
|
||||
"Read the Setup Guide</a>";
|
||||
|
||||
var title = "Missing configuration volume";
|
||||
CoreDialog.fatal(title, message);
|
||||
};
|
||||
|
||||
$scope.parseDbUri = function(value) {
|
||||
if (!value) { return null; }
|
||||
|
||||
// Format: mysql+pymysql://<username>:<url escaped password>@<hostname>/<database_name>
|
||||
var uri = URI(value);
|
||||
return {
|
||||
'kind': uri.protocol(),
|
||||
'username': uri.username(),
|
||||
'password': uri.password(),
|
||||
'server': uri.host(),
|
||||
'database': uri.path() ? uri.path().substr(1) : ''
|
||||
};
|
||||
};
|
||||
|
||||
$scope.serializeDbUri = function(fields) {
|
||||
if (!fields['server']) { return ''; }
|
||||
if (!fields['database']) { return ''; }
|
||||
|
||||
var uri = URI();
|
||||
try {
|
||||
uri = uri && uri.host(fields['server']);
|
||||
uri = uri && uri.protocol(fields['kind']);
|
||||
uri = uri && uri.username(fields['username']);
|
||||
uri = uri && uri.password(fields['password']);
|
||||
uri = uri && uri.path('/' + (fields['database'] || ''));
|
||||
uri = uri && uri.toString();
|
||||
} catch (ex) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return uri;
|
||||
};
|
||||
|
||||
$scope.createSuperUser = function() {
|
||||
$scope.currentStep = $scope.States.CREATING_SUPERUSER;
|
||||
ApiService.scCreateInitialSuperuser($scope.superUser, null).then(function(resp) {
|
||||
UserService.load();
|
||||
$scope.checkStatus();
|
||||
}, function(resp) {
|
||||
$scope.currentStep = $scope.States.SUPERUSER_ERROR;
|
||||
$scope.errors.SuperuserCreationError = ApiService.getErrorMessage(resp, 'Could not create superuser');
|
||||
});
|
||||
};
|
||||
|
||||
$scope.performDatabaseSetup = function() {
|
||||
$scope.currentStep = $scope.States.DB_SETUP;
|
||||
ApiService.scSetupDatabase(null, null).then(function(resp) {
|
||||
if (resp['error']) {
|
||||
$scope.currentStep = $scope.States.DB_SETUP_ERROR;
|
||||
$scope.errors.DatabaseSetupError = resp['error'];
|
||||
} else {
|
||||
$scope.currentStep = $scope.States.DB_SETUP_SUCCESS;
|
||||
}
|
||||
}, ApiService.errorDisplay('Could not setup database. Please report this to support.'))
|
||||
};
|
||||
|
||||
$scope.validateDatabase = function() {
|
||||
$scope.currentStep = $scope.States.VALIDATING_DB;
|
||||
$scope.databaseInvalid = null;
|
||||
|
||||
var data = {
|
||||
'config': {
|
||||
'DB_URI': $scope.databaseUri
|
||||
},
|
||||
'hostname': window.location.host
|
||||
};
|
||||
|
||||
if ($scope.currentState.hasDatabaseSSLCert) {
|
||||
data['config']['DB_CONNECTION_ARGS'] = {
|
||||
'ssl': {
|
||||
'ca': 'conf/stack/database.pem'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var params = {
|
||||
'service': 'database'
|
||||
};
|
||||
|
||||
ApiService.scValidateConfig(data, params).then(function(resp) {
|
||||
var status = resp.status;
|
||||
|
||||
if (status) {
|
||||
$scope.currentStep = $scope.States.SAVING_DB;
|
||||
ApiService.scUpdateConfig(data, null).then(function(resp) {
|
||||
$scope.checkStatus();
|
||||
}, ApiService.errorDisplay('Cannot update config. Please report this to support'));
|
||||
} else {
|
||||
$scope.currentStep = $scope.States.DB_ERROR;
|
||||
$scope.errors.DatabaseValidationError = resp.reason;
|
||||
}
|
||||
}, ApiService.errorDisplay('Cannot validate database. Please report this to support'));
|
||||
};
|
||||
|
||||
$scope.checkStatus = function() {
|
||||
ContainerService.checkStatus(function(resp) {
|
||||
$scope.currentStep = resp['status'];
|
||||
}, $scope.currentConfig);
|
||||
};
|
||||
|
||||
// Load the initial status.
|
||||
$scope.checkStatus();
|
||||
};
|
||||
})();
|
|
@ -18,7 +18,6 @@ var quayDependencies: string[] = [
|
|||
'pasvaz.bindonce',
|
||||
'ansiToHtml',
|
||||
'core-ui',
|
||||
'core-config-setup',
|
||||
'infinite-scroll',
|
||||
'ngTagsInput',
|
||||
];
|
||||
|
|
|
@ -49,8 +49,7 @@ function provideRoutes($routeProvider: ng.route.IRouteProvider,
|
|||
if (INJECTED_FEATURES.SUPER_USERS) {
|
||||
// QE Management
|
||||
routeBuilder.route('/superuser/', 'superuser')
|
||||
// QE Setup
|
||||
.route('/setup/', 'setup');
|
||||
.route('/incomplete-setup/', 'incomplete-setup');
|
||||
}
|
||||
|
||||
routeBuilder
|
||||
|
|
21
static/partials/incomplete-setup.html
Normal file
21
static/partials/incomplete-setup.html
Normal file
|
@ -0,0 +1,21 @@
|
|||
<div>
|
||||
<div class="cor-loader" ng-show="currentStep == States.LOADING"></div>
|
||||
<div class="page-content" quay-show="Features.SUPER_USERS">
|
||||
<div class="cor-title">
|
||||
<span class="cor-title-link"></span>
|
||||
<span class="cor-title-content">Quay Enterprise Setup Incomplete</span>
|
||||
</div>
|
||||
|
||||
<div class="co-main-content-panel" style="padding: 20px;">
|
||||
<div class="co-alert co-alert-warning">
|
||||
<div><strong>Your configuration is not setup yet</strong></div>
|
||||
<div>Please refer to
|
||||
<a target="_blank" href="https://coreos.com/quay-enterprise/docs/latest/initial-setup.html">
|
||||
the docs to set up your instance.
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,307 +0,0 @@
|
|||
<div>
|
||||
<div class="cor-loader" ng-show="currentStep == States.LOADING"></div>
|
||||
<div class="page-content" quay-show="Features.SUPER_USERS && currentStep == States.CONFIG">
|
||||
<div class="cor-title">
|
||||
<span class="cor-title-link"></span>
|
||||
<span class="cor-title-content">Quay Enterprise Setup</span>
|
||||
</div>
|
||||
|
||||
<div class="co-main-content-panel" style="padding: 20px;">
|
||||
<div class="co-alert alert alert-info">
|
||||
<span class="cor-step-bar" progress="stepProgress">
|
||||
<span class="cor-step" title="Configure Database" text="1"></span>
|
||||
<span class="cor-step" title="Setup Database" icon="database"></span>
|
||||
<span class="cor-step" title="Container Restart" icon="refresh"></span>
|
||||
<span class="cor-step" title="Create Superuser" text="2"></span>
|
||||
<span class="cor-step" title="Configure Registry" text="3"></span>
|
||||
<span class="cor-step" title="Validate Configuration" text="4"></span>
|
||||
<span class="cor-step" title="Container Restart" icon="refresh"></span>
|
||||
<span class="cor-step" title="Setup Complete" icon="check"></span>
|
||||
</span>
|
||||
|
||||
<div><strong>Almost done!</strong></div>
|
||||
<div>Configure your Redis database and other settings below</div>
|
||||
</div>
|
||||
|
||||
<div class="config-setup-tool" is-active="isStep(currentStep, States.CONFIG)"
|
||||
configuration-saved="configurationSaved(config)"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal message dialog -->
|
||||
<div class="co-dialog modal fade initial-setup-modal" id="setupModal">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<!-- Header -->
|
||||
<div class="modal-header">
|
||||
<span class="cor-step-bar" progress="stepProgress">
|
||||
<span class="cor-step" title="Configure Database" text="1"></span>
|
||||
<span class="cor-step" title="Setup Database" icon="database"></span>
|
||||
<span class="cor-step" title="Container Restart" icon="refresh"></span>
|
||||
<span class="cor-step" title="Create Superuser" text="2"></span>
|
||||
<span class="cor-step" title="Configure Registry" text="3"></span>
|
||||
<span class="cor-step" title="Validate Configuration" text="4"></span>
|
||||
<span class="cor-step" title="Container Restart" icon="refresh"></span>
|
||||
<span class="cor-step" title="Setup Complete" icon="check"></span>
|
||||
</span>
|
||||
<h4 class="modal-title"><span><span class="registry-name" is-short="true"></span> Setup</h4>
|
||||
</div>
|
||||
|
||||
<form id="superuserForm" name="superuserForm" ng-submit="createSuperUser()">
|
||||
<!-- Content: CREATE_SUPERUSER or SUPERUSER_ERROR or CREATING_SUPERUSER -->
|
||||
<div class="modal-body config-setup-tool-element" style="padding: 20px"
|
||||
ng-show="isStep(currentStep, States.CREATE_SUPERUSER, States.SUPERUSER_ERROR, States.CREATING_SUPERUSER)">
|
||||
<p>A superuser is the main administrator of your <span class="registry-name" is-short="true"></span>. Only superusers can edit configuration settings.</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Username</label>
|
||||
<input class="form-control" type="text" ng-model="superUser.username"
|
||||
ng-pattern="/^[a-z0-9_]{4,30}$/" required>
|
||||
<div class="help-text">Minimum 4 characters in length</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Email address</label>
|
||||
<input class="form-control" type="email" ng-model="superUser.email" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Password</label>
|
||||
<input class="form-control" type="password" ng-model="superUser.password"
|
||||
ng-pattern="/^[^\s]+$/"
|
||||
ng-minlength="8" required>
|
||||
<div class="help-text">Minimum 8 characters in length</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Repeat Password</label>
|
||||
<input class="form-control" type="password" ng-model="superUser.repeatPassword"
|
||||
match="superUser.password" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Footer: CREATE_SUPERUSER or SUPERUSER_ERROR -->
|
||||
<div class="modal-footer"
|
||||
ng-show="isStep(currentStep, States.CREATE_SUPERUSER, States.SUPERUSER_ERROR)">
|
||||
<button type="submit" class="btn btn-primary" ng-disabled="!superuserForm.$valid">
|
||||
Create Super User
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- Content: DB_RESTARTING or CONFIG_RESTARTING -->
|
||||
<div class="modal-body" style="padding: 20px;"
|
||||
ng-show="isStep(currentStep, States.DB_RESTARTING, States.CONFIG_RESTARTING)">
|
||||
<h4 style="margin-bottom: 20px;">
|
||||
<i class="fa fa-lg fa-refresh" style="margin-right: 10px;"></i>
|
||||
<span class="registry-name"></span> is currently being restarted
|
||||
</h4>
|
||||
This can take several minutes. If the container does not restart on its own,
|
||||
please re-execute the <code>docker run</code> command.
|
||||
</div>
|
||||
|
||||
<!-- Content: READY -->
|
||||
<div class="modal-body" style="padding: 20px;"
|
||||
ng-show="isStep(currentStep, States.READY)">
|
||||
<h4>Installation and setup of <span class="registry-name"></span> is complete</h4>
|
||||
You can now invite users to join, create organizations and start pushing and pulling
|
||||
repositories.
|
||||
|
||||
<strong ng-if="hasSSL" style="margin-top: 20px;">
|
||||
Note: SSL is enabled. Please make sure to visit with
|
||||
an <u>https</u> prefix
|
||||
</strong>
|
||||
</div>
|
||||
|
||||
<!-- Content: VALID_CONFIG -->
|
||||
<div class="modal-body" style="padding: 20px;"
|
||||
ng-show="isStep(currentStep, States.VALID_CONFIG)">
|
||||
<h4>All configuration has been validated and saved</h4>
|
||||
The container must be restarted to apply the configuration changes.
|
||||
</div>
|
||||
|
||||
<!-- Content: DB_SETUP_SUCCESS -->
|
||||
<div class="modal-body" style="padding: 20px;"
|
||||
ng-show="isStep(currentStep, States.DB_SETUP_SUCCESS)">
|
||||
<h4>The database has been setup and is ready</h4>
|
||||
The container must be restarted to apply the configuration changes.
|
||||
</div>
|
||||
|
||||
<!-- Content: DB_SETUP or DB_SETUP_ERROR -->
|
||||
<div class="modal-body" style="padding: 20px;"
|
||||
ng-show="isStep(currentStep, States.DB_SETUP, States.DB_SETUP_ERROR)">
|
||||
<h4>
|
||||
<i class="fa fa-lg fa-database" style="margin-right: 10px;"></i>
|
||||
<span class="registry-name"></span> is currently setting up its database
|
||||
schema
|
||||
</h4>
|
||||
This can take several minutes.
|
||||
</div>
|
||||
|
||||
<!-- Content: CONFIG_DB or DB_ERROR or VALIDATING_DB or SAVING_DB -->
|
||||
<div class="modal-body validate-database config-setup-tool-element"
|
||||
ng-show="isStep(currentStep, States.CONFIG_DB, States.DB_ERROR, States.VALIDATING_DB, States.SAVING_DB)">
|
||||
<p>
|
||||
Please enter the connection details for your <strong>empty</strong> database. The schema will be created in the following step.</p>
|
||||
</p>
|
||||
|
||||
<div class="config-parsed-field" binding="databaseUri"
|
||||
parser="parseDbUri(value)"
|
||||
serializer="serializeDbUri(fields)">
|
||||
<table class="config-table">
|
||||
<tr>
|
||||
<td class="non-input">Database Type:</td>
|
||||
<td>
|
||||
<select ng-model="fields.kind">
|
||||
<option value="mysql+pymysql">MySQL</option>
|
||||
<option value="postgresql">Postgres</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-show="fields.kind">
|
||||
<td>Database Server:</td>
|
||||
<td>
|
||||
<span class="config-string-field" binding="fields.server"
|
||||
placeholder="dbserverhost"
|
||||
pattern="{{ HOSTNAME_REGEX }}"
|
||||
validator="validateHostname(value)">></span>
|
||||
<div class="help-text">
|
||||
The server (and optionally, custom port) where the database lives
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-show="fields.kind">
|
||||
<td>Username:</td>
|
||||
<td>
|
||||
<span class="config-string-field" binding="fields.username"
|
||||
placeholder="someuser"></span>
|
||||
<div class="help-text">This user must have <strong>full access</strong> to the database</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-show="fields.kind">
|
||||
<td>Password:</td>
|
||||
<td>
|
||||
<input class="form-control" type="password" ng-model="fields.password"></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-show="fields.kind">
|
||||
<td>Database Name:</td>
|
||||
<td>
|
||||
<span class="config-string-field" binding="fields.database"
|
||||
placeholder="registry-database"></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-show="fields.kind">
|
||||
<td>SSL Certificate:</td>
|
||||
<td>
|
||||
<span class="config-file-field" filename="database.pem"
|
||||
skip-check-file="true" has-file="currentState.hasDatabaseSSLCert"></span>
|
||||
<div class="help-text">Optional SSL certicate (in PEM format) to use to connect to the database</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Footer: CREATING_SUPERUSER -->
|
||||
<div class="modal-footer working" ng-show="isStep(currentStep, States.CREATING_SUPERUSER)">
|
||||
<span class="cor-loader-inline"></span> Creating superuser...
|
||||
</div>
|
||||
|
||||
<!-- Footer: SUPERUSER_ERROR -->
|
||||
<div class="modal-footer alert alert-warning"
|
||||
ng-show="isStep(currentStep, States.SUPERUSER_ERROR)">
|
||||
{{ errors.SuperuserCreationError }}
|
||||
</div>
|
||||
|
||||
<!-- Footer: DB_SETUP_ERROR -->
|
||||
<div class="modal-footer alert alert-warning"
|
||||
ng-show="isStep(currentStep, States.DB_SETUP_ERROR)">
|
||||
Database Setup Failed. Please report this to support: {{ errors.DatabaseSetupError }}
|
||||
</div>
|
||||
|
||||
<!-- Footer: DB_ERROR -->
|
||||
<div class="modal-footer alert alert-warning" ng-show="isStep(currentStep, States.DB_ERROR)">
|
||||
Database Validation Issue: {{ errors.DatabaseValidationError }}
|
||||
</div>
|
||||
|
||||
<!-- Footer: CONFIG_DB or DB_ERROR -->
|
||||
<div class="modal-footer"
|
||||
ng-show="isStep(currentStep, States.CONFIG_DB, States.DB_ERROR)">
|
||||
<span class="left-align" ng-show="isStep(currentStep, States.DB_ERROR)">
|
||||
<i class="fa fa-warning"></i>
|
||||
Problem Detected
|
||||
</span>
|
||||
|
||||
<button type="submit" class="btn btn-primary"
|
||||
ng-disabled="!databaseUri"
|
||||
ng-click="validateDatabase()">
|
||||
Validate Database Settings
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Footer: READY -->
|
||||
<div class="modal-footer"
|
||||
ng-show="isStep(currentStep, States.READY)">
|
||||
<span class="left-align">
|
||||
<i class="fa fa-check"></i>
|
||||
Installation Complete!
|
||||
</span>
|
||||
|
||||
<a ng-click="showSuperuserPanel()" class="btn btn-primary">
|
||||
View Superuser Panel
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Footer: VALID_CONFIG -->
|
||||
<div class="modal-footer"
|
||||
ng-show="isStep(currentStep, States.VALID_CONFIG)">
|
||||
<span class="left-align">
|
||||
<i class="fa fa-check"></i>
|
||||
Configuration Validated and Saved
|
||||
</span>
|
||||
|
||||
<button type="submit" class="btn btn-primary"
|
||||
ng-click="restartContainer(States.CONFIG_RESTARTING)">
|
||||
Restart Container
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Footer: DB_SETUP_SUCCESS -->
|
||||
<div class="modal-footer"
|
||||
ng-show="isStep(currentStep, States.DB_SETUP_SUCCESS)">
|
||||
<span class="left-align">
|
||||
<i class="fa fa-check"></i>
|
||||
Database Setup and Ready
|
||||
</span>
|
||||
|
||||
<button type="submit" class="btn btn-primary"
|
||||
ng-click="restartContainer(States.DB_RESTARTING)">
|
||||
Restart Container
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Footer: DB_SETUP -->
|
||||
<div class="modal-footer working" ng-show="isStep(currentStep, States.DB_SETUP)">
|
||||
<span class="cor-loader-inline"></span> Setting up database...
|
||||
</div>
|
||||
|
||||
<!-- Footer: SAVING_DB -->
|
||||
<div class="modal-footer working" ng-show="isStep(currentStep, States.SAVING_DB)">
|
||||
<span class="cor-loader-inline"></span> Saving database configuration...
|
||||
</div>
|
||||
|
||||
<!-- Footer: VALIDATING_DB -->
|
||||
<div class="modal-footer working" ng-show="isStep(currentStep, States.VALIDATING_DB)">
|
||||
<span class="cor-loader-inline"></span> Testing database settings...
|
||||
</div>
|
||||
|
||||
<!-- Footer: DB_RESTARTING or CONFIG_RESTARTING-->
|
||||
<div class="modal-footer working"
|
||||
ng-show="isStep(currentStep, States.DB_RESTARTING, States.CONFIG_RESTARTING)">
|
||||
<span class="cor-loader-inline"></span> Waiting for container to restart...
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
|
@ -46,10 +46,6 @@
|
|||
tab-init="loadDebugServices()">
|
||||
<i class="fa fa-bug"></i>
|
||||
</cor-tab>
|
||||
<cor-tab tab-title="Registry Settings" tab-id="setup"
|
||||
tab-init="loadConfig()">
|
||||
<i class="fa fa-cog"></i>
|
||||
</cor-tab>
|
||||
<cor-tab tab-title="Globally visible user messages" tab-id="message-of-the-day"
|
||||
tab-init="loadMessageOfTheDay()">
|
||||
<i class="fa fa-newspaper-o"></i>
|
||||
|
@ -62,15 +58,6 @@
|
|||
</cor-tabs>
|
||||
|
||||
<cor-tab-content>
|
||||
<!-- Setup tab -->
|
||||
<cor-tab-pane id="setup">
|
||||
<div class="co-alert co-alert-warning" ng-if="configProviderId != 'k8s'">
|
||||
<strong>Warning:</strong> If you are running Quay Enterprise under multiple containers, additional actions are necessary in order to apply any configuration changes made here to the entire cluster. It is recommended to make (and validate) configuration changes here, then copy your configuration to all instances and restart them.
|
||||
</div>
|
||||
<div class="config-setup-tool" is-active="configStatus == 'ready'"
|
||||
configuration-saved="configurationSaved(config)"></div>
|
||||
</cor-tab-pane>
|
||||
|
||||
<!-- Super user build logs tab-->
|
||||
<cor-tab-pane id="super-user-build-logs">
|
||||
<div class="super-user-build-logs" is-enabled="superUserBuildLogsActive"></div>
|
||||
|
|
Reference in a new issue