Create download modal following setup completion
This commit is contained in:
parent
aa93d698b2
commit
2d0a599aab
12 changed files with 142 additions and 52 deletions
|
@ -65,7 +65,6 @@ class SuperUserConfig(ApiResource):
|
||||||
""" Updates the config override file. """
|
""" Updates the config override file. """
|
||||||
# Note: This method is called to set the database configuration before super users exists,
|
# Note: This method is called to set the database configuration before super users exists,
|
||||||
# so we also allow it to be called if there is no valid registry configuration setup.
|
# so we also allow it to be called if there is no valid registry configuration setup.
|
||||||
if not config_provider.config_exists():
|
|
||||||
config_object = request.get_json()['config']
|
config_object = request.get_json()['config']
|
||||||
hostname = request.get_json()['hostname']
|
hostname = request.get_json()['hostname']
|
||||||
|
|
||||||
|
@ -101,9 +100,6 @@ class SuperUserConfig(ApiResource):
|
||||||
'config': config_object
|
'config': config_object
|
||||||
}
|
}
|
||||||
|
|
||||||
abort(403)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@resource('/v1/superuser/registrystatus')
|
@resource('/v1/superuser/registrystatus')
|
||||||
class SuperUserRegistryStatus(ApiResource):
|
class SuperUserRegistryStatus(ApiResource):
|
||||||
|
|
|
@ -37,15 +37,14 @@ class TarConfigLoader(ApiResource):
|
||||||
if os.path.isfile('quay-config.tar.gz'):
|
if os.path.isfile('quay-config.tar.gz'):
|
||||||
os.remove('quay-config.tar.gz')
|
os.remove('quay-config.tar.gz')
|
||||||
|
|
||||||
tar = tarfile.open('quay-config.tar.gz', mode="w:gz")
|
tar = tarfile.open('quay-config.tar.gz', mode="w|gz")
|
||||||
|
|
||||||
for name in os.listdir(config_path):
|
for name in os.listdir(config_path):
|
||||||
tar.add(os.path.join(config_path, name), filter=tarinfo_filter)
|
tar.add(os.path.join(config_path, name), filter=tarinfo_filter)
|
||||||
|
|
||||||
tar.close()
|
tar.close()
|
||||||
|
|
||||||
return send_file('quay-config.tar.gz', mimetype='application/gzip',
|
return send_file('quay-config.tar.gz', mimetype='application/gzip')
|
||||||
as_attachment=True, attachment_filename='quay-config.tar.gz')
|
|
||||||
|
|
||||||
@nickname('scUploadTarballConfig')
|
@nickname('scUploadTarballConfig')
|
||||||
def put(self):
|
def put(self):
|
||||||
|
|
|
@ -22,5 +22,6 @@
|
||||||
</div><!-- /.modal-dialog -->
|
</div><!-- /.modal-dialog -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div ng-if="$ctrl.state === 'setup'" class="setup"></div>
|
<div ng-if="$ctrl.state === 'setup'" class="setup" setup-completed="$ctrl.setupCompleted()"></div>
|
||||||
<load-config ng-if="$ctrl.state === 'load'" config-loaded="$ctrl.configLoaded()"></load-config>
|
<load-config ng-if="$ctrl.state === 'load'" config-loaded="$ctrl.configLoaded()"></load-config>
|
||||||
|
<download-tarball-modal ng-if="$ctrl.state === 'download'" loaded-config="$ctrl.loadedConfig"></download-tarball-modal>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Input, Component, Inject } from 'ng-metadata/core';
|
import { Component } from 'ng-metadata/core';
|
||||||
const templateUrl = require('./config-setup-app.component.html');
|
const templateUrl = require('./config-setup-app.component.html');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -9,7 +9,13 @@ const templateUrl = require('./config-setup-app.component.html');
|
||||||
templateUrl: templateUrl,
|
templateUrl: templateUrl,
|
||||||
})
|
})
|
||||||
export class ConfigSetupAppComponent {
|
export class ConfigSetupAppComponent {
|
||||||
private state: 'choice' | 'setup' | 'load';
|
private state
|
||||||
|
: 'choice'
|
||||||
|
| 'setup'
|
||||||
|
| 'load'
|
||||||
|
| 'download';
|
||||||
|
|
||||||
|
private loadedConfig = false;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.state = 'choice';
|
this.state = 'choice';
|
||||||
|
@ -21,9 +27,14 @@ export class ConfigSetupAppComponent {
|
||||||
|
|
||||||
private chooseLoad(): void {
|
private chooseLoad(): void {
|
||||||
this.state = 'load';
|
this.state = 'load';
|
||||||
|
this.loadedConfig = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private configLoaded(): void {
|
private configLoaded(): void {
|
||||||
this.state = 'setup';
|
this.state = 'setup';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private setupCompleted(): void {
|
||||||
|
this.state = 'download';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
<div>
|
||||||
|
<div class="co-dialog modal fade initial-setup-modal in" id="setupModal" style="display: block;">
|
||||||
|
<div class="modal-backdrop fade in" style="height: 1000px;"></div>
|
||||||
|
<div class="modal-dialog fade in">
|
||||||
|
<div class="modal-content">
|
||||||
|
<!-- Header -->
|
||||||
|
<div class="modal-header">
|
||||||
|
<h4 class="modal-title"><span>Download Configuration</span></h4>
|
||||||
|
</div>
|
||||||
|
<!-- Body -->
|
||||||
|
<div class="modal-body">
|
||||||
|
<div ng-if="$ctrl.loadedConfig">
|
||||||
|
Please download your updated configuration. To deploy these changes to your Quay Enterprise instances, please
|
||||||
|
<a target="_blank" href="https://coreos.com/quay-enterprise/docs/latest/initial-setup.html">
|
||||||
|
see the docs.
|
||||||
|
</a>
|
||||||
|
<div class="modal__warning-box">
|
||||||
|
<i class="fas fa-exclamation-triangle" style="margin-right: 10px;"></i><strong>Warning:</strong>
|
||||||
|
Your configuration and certificates are kept <i>unencrypted</i>. Please keep this file secure.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div ng-if="!$ctrl.loadedConfig">
|
||||||
|
Please download your new configuration. For more information, and next steps, please
|
||||||
|
<a target="_blank" href="https://coreos.com/quay-enterprise/docs/latest/initial-setup.html">
|
||||||
|
see the docs.
|
||||||
|
</a>
|
||||||
|
<div class="modal__warning-box">
|
||||||
|
<i class="fas fa-exclamation-triangle" style="margin-right: 10px;"></i><strong>Warning: </strong>
|
||||||
|
Your configuration and certificates are kept <i>unencrypted</i>. Please keep this file secure.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button class="btn btn-primary"
|
||||||
|
ng-click="$ctrl.downloadTarball()">
|
||||||
|
<i class="fa fa-download" style="margin-right: 10px;"></i>Download Configuration
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div><!-- /.modal-content -->
|
||||||
|
</div><!-- /.modal-dialog -->
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -0,0 +1,34 @@
|
||||||
|
import { Input, Component, Inject } from 'ng-metadata/core';
|
||||||
|
const templateUrl = require('./download-tarball-modal.component.html');
|
||||||
|
const styleUrl = require('./download-tarball-modal.css');
|
||||||
|
|
||||||
|
declare const FileSaver: any;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initial Screen and Choice in the Config App
|
||||||
|
*/
|
||||||
|
@Component({
|
||||||
|
selector: 'download-tarball-modal',
|
||||||
|
templateUrl: templateUrl,
|
||||||
|
styleUrls: [ styleUrl ],
|
||||||
|
})
|
||||||
|
export class DownloadTarballModalComponent {
|
||||||
|
@Input('<') public loadedConfig;
|
||||||
|
|
||||||
|
constructor(@Inject('ApiService') private ApiService) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private downloadTarball() {
|
||||||
|
const errorDisplay: Function = this.ApiService.errorDisplay(
|
||||||
|
'Could not save configuration. Please report this error.'
|
||||||
|
);
|
||||||
|
|
||||||
|
// We need to set the response type to 'blob', to ensure it's never encoded as a string
|
||||||
|
// (string encoded binary data can be difficult to transform with js)
|
||||||
|
// and to make it easier to save (FileSaver expects a blob)
|
||||||
|
this.ApiService.scGetConfigTarball(null, null, null, null, true).then(function(resp) {
|
||||||
|
FileSaver.saveAs(resp, 'quay-config.tar.gz');
|
||||||
|
}, errorDisplay);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
.modal__warning-box {
|
||||||
|
background-color: #ddd;
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 5px;
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ import { NgModule } from 'ng-metadata/core';
|
||||||
import * as restangular from 'restangular';
|
import * as restangular from 'restangular';
|
||||||
|
|
||||||
import { ConfigSetupAppComponent } from './components/config-setup-app/config-setup-app.component';
|
import { ConfigSetupAppComponent } from './components/config-setup-app/config-setup-app.component';
|
||||||
|
import { DownloadTarballModalComponent } from './components/download-tarball-modal/download-tarball-modal.component';
|
||||||
import { LoadConfigComponent } from './components/load-config/load-config.component';
|
import { LoadConfigComponent } from './components/load-config/load-config.component';
|
||||||
|
|
||||||
const quayDependencies: string[] = [
|
const quayDependencies: string[] = [
|
||||||
|
@ -42,6 +43,7 @@ function provideConfig($provide: ng.auto.IProvideService,
|
||||||
imports: [ DependencyConfig ],
|
imports: [ DependencyConfig ],
|
||||||
declarations: [
|
declarations: [
|
||||||
ConfigSetupAppComponent,
|
ConfigSetupAppComponent,
|
||||||
|
DownloadTarballModalComponent,
|
||||||
LoadConfigComponent,
|
LoadConfigComponent,
|
||||||
],
|
],
|
||||||
providers: []
|
providers: []
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
<div class="config-setup-tool-element">
|
<div class="config-setup-tool-element">
|
||||||
<div class="cor-loader" ng-if="!config"></div>
|
<div class="cor-loader" ng-if="!config"></div>
|
||||||
<div ng-show="true">
|
<div ng-show="true">
|
||||||
<!--<div ng-show="config && config['SUPER_USERS']">-->
|
|
||||||
<form id="configform" name="configform">
|
<form id="configform" name="configform">
|
||||||
|
|
||||||
<!-- Custom SSL certificates -->
|
<!-- Custom SSL certificates -->
|
||||||
|
@ -1630,9 +1629,9 @@
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<button class="btn btn-primary"
|
<button class="btn btn-primary"
|
||||||
ng-click="generateConfigTarball()"
|
ng-click="saveConfiguration()"
|
||||||
ng-disabled="savingConfiguration">
|
ng-disabled="savingConfiguration">
|
||||||
<i class="fa fa-upload" style="margin-right: 10px;"></i>Generate Configuration
|
Next
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,8 @@ angular.module("quay-config")
|
||||||
restrict: 'C',
|
restrict: 'C',
|
||||||
scope: {
|
scope: {
|
||||||
'isActive': '=isActive',
|
'isActive': '=isActive',
|
||||||
'configurationSaved': '&configurationSaved'
|
'configurationSaved': '&configurationSaved',
|
||||||
|
'setupCompleted': '&setupCompleted',
|
||||||
},
|
},
|
||||||
controller: function($rootScope, $scope, $element, $timeout, ApiService) {
|
controller: function($rootScope, $scope, $element, $timeout, ApiService) {
|
||||||
var authPassword = null;
|
var authPassword = null;
|
||||||
|
@ -413,7 +414,7 @@ angular.module("quay-config")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.generateConfigTarball = function() {
|
$scope.saveConfiguration = function() {
|
||||||
$scope.savingConfiguration = true;
|
$scope.savingConfiguration = true;
|
||||||
|
|
||||||
// Make sure to note that fully verified setup is completed. We use this as a signal
|
// Make sure to note that fully verified setup is completed. We use this as a signal
|
||||||
|
@ -432,20 +433,16 @@ angular.module("quay-config")
|
||||||
authPassword = null;
|
authPassword = null;
|
||||||
});
|
});
|
||||||
|
|
||||||
// We need to set the response type to 'blob', to ensure it's never encoded as a string
|
ApiService.scUpdateConfig(data).then(function(resp) {
|
||||||
// (string encoded binary data can be difficult to transform with js)
|
|
||||||
// and to make it easier to save (FileSaver expects a blob)
|
|
||||||
ApiService.scGetConfigTarball(null, null, null, null, true).then(function(resp) {
|
|
||||||
authPassword = null;
|
authPassword = null;
|
||||||
|
|
||||||
FileSaver.saveAs(resp, 'quay-config.tar.gz');
|
|
||||||
|
|
||||||
$scope.savingConfiguration = false;
|
$scope.savingConfiguration = false;
|
||||||
$scope.mapped.$hasChanges = false;
|
$scope.mapped.$hasChanges = false;
|
||||||
|
|
||||||
$('#validateAndSaveModal').modal('hide');
|
$('#validateAndSaveModal').modal('hide');
|
||||||
|
|
||||||
$scope.configurationSaved({'config': $scope.config});
|
// $scope.configurationSaved({'config': $scope.config});
|
||||||
|
$scope.setupCompleted();
|
||||||
}, errorDisplay);
|
}, errorDisplay);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,8 @@ const templateUrl = require('./setup.html');
|
||||||
restrict: 'C',
|
restrict: 'C',
|
||||||
scope: {
|
scope: {
|
||||||
'isActive': '=isActive',
|
'isActive': '=isActive',
|
||||||
'configurationSaved': '&configurationSaved'
|
'configurationSaved': '&configurationSaved',
|
||||||
|
'setupCompleted': '&setupCompleted',
|
||||||
},
|
},
|
||||||
controller: SetupCtrl,
|
controller: SetupCtrl,
|
||||||
};
|
};
|
||||||
|
|
|
@ -25,7 +25,9 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="config-setup-tool" is-active="isStep(currentStep, States.CONFIG)"
|
<div class="config-setup-tool" is-active="isStep(currentStep, States.CONFIG)"
|
||||||
configuration-saved="configurationSaved(config)"></divconfig-setup-tool>
|
configuration-saved="configurationSaved(config)"
|
||||||
|
setup-completed="setupCompleted()"
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Reference in a new issue