diff --git a/config_app/config_endpoints/api/suconfig.py b/config_app/config_endpoints/api/suconfig.py index f7dc232b1..9ec395a05 100644 --- a/config_app/config_endpoints/api/suconfig.py +++ b/config_app/config_endpoints/api/suconfig.py @@ -1,7 +1,4 @@ import logging -import os -import subprocess -import signal from flask import abort, request @@ -14,9 +11,7 @@ from data.users import get_federated_service_name, get_users_handler from data.database import configure from data.runmigration import run_alembic_migration from util.config.configutil import add_enterprise_config_defaults -from util.config.database import sync_database_with_config from util.config.validator import validate_service_for_config, ValidatorContext, is_valid_config_upload_filename -from util.config.validators import LocalStorageConfigValidationException logger = logging.getLogger(__name__) diff --git a/config_app/config_endpoints/api/superuser.py b/config_app/config_endpoints/api/superuser.py index 0a4705d03..34bb9fba9 100644 --- a/config_app/config_endpoints/api/superuser.py +++ b/config_app/config_endpoints/api/superuser.py @@ -4,15 +4,16 @@ import os from flask import request, jsonify +from util.config.validator import EXTRA_CA_DIRECTORY + from config_app.config_endpoints.exception import InvalidRequest from config_app.config_endpoints.api import resource, ApiResource, nickname +from config_app.config_endpoints.api.superuser_models_pre_oci import pre_oci_model from config_app.config_util.ssl import load_certificate, CertInvalidException from config_app.c_app import app, config_provider -from config_app.config_endpoints.api.superuser_models_pre_oci import pre_oci_model logger = logging.getLogger(__name__) -EXTRA_CA_DIRECTORY = 'extra_ca_certs' @resource('/v1/superuser/customcerts/') diff --git a/config_app/config_endpoints/api/tar_config_loader.py b/config_app/config_endpoints/api/tar_config_loader.py index e16b8a092..f9b61e740 100644 --- a/config_app/config_endpoints/api/tar_config_loader.py +++ b/config_app/config_endpoints/api/tar_config_loader.py @@ -1,17 +1,53 @@ +import os import tarfile -from flask import request, make_response +from flask import request, make_response, send_file from data.database import configure +from util.config.validator import EXTRA_CA_DIRECTORY from config_app.c_app import app, config_provider from config_app.config_endpoints.api import resource, ApiResource, nickname @resource('/v1/configapp/tarconfig') class TarConfigLoader(ApiResource): - """ Resource for validating a block of configuration against an external service. """ + """ + Resource for dealing with configuration as a tarball, + including loading and generating functions + """ - @nickname('uploadTarballConfig') + @nickname('scGetConfigTarball') + def get(self): + config_path = config_provider.config_volume + + # remove the initial trailing / from the prefix path, and add the last dir one + tar_dir_prefix = config_path[1:] + '/' + + def tarinfo_filter(tarinfo): + # remove leading directory info + tarinfo.name = tarinfo.name.replace(tar_dir_prefix, '') + + # ignore any directory that isn't the specified extra ca one: + if tarinfo.isdir() and not tarinfo.name == EXTRA_CA_DIRECTORY: + return None + + return tarinfo + + # Remove the tar if it already exists so we don't write on top of existing tarball + if os.path.isfile('quay-config.tar.gz'): + os.remove('quay-config.tar.gz') + + tar = tarfile.open('quay-config.tar.gz', mode="w:gz") + + for name in os.listdir(config_path): + tar.add(os.path.join(config_path, name), filter=tarinfo_filter) + + tar.close() + + return send_file('quay-config.tar.gz', mimetype='application/gzip', + as_attachment=True, attachment_filename='quay-config.tar.gz') + + @nickname('scUploadTarballConfig') def put(self): """ Loads tarball config into the config provider """ input_stream = request.stream diff --git a/config_app/js/config-field-templates/config-setup-tool.html b/config_app/js/config-field-templates/config-setup-tool.html deleted file mode 100644 index 9c4dde631..000000000 --- a/config_app/js/config-field-templates/config-setup-tool.html +++ /dev/null @@ -1,1656 +0,0 @@ -
-
-
-
- - -
-
- Custom SSL Certificates -
-
-
-
-
- - -
-
- Basic Configuration -
-
- - - - - - - - - - -
Enterprise Logo URL: - -
- Enter the full URL to your company's logo. -
-
- -
Contact Information: - -
- Information to show in the Contact Page. If none specified, CoreOS contact information - is displayed. -
-
-
-
- - -
-
- Server Configuration -
-
- - - - - - - - - -
Server Hostname: - -
- The HTTP host (and optionally the port number if a non-standard HTTP/HTTPS port) of the location - where the registry will be accessible on the network -
-
TLS: - - -
- Running without TLS should not be used for production workloads! -
- -
- Terminating TLS outside of Quay Enterprise can result in unusual behavior if the external load balancer is not - configured properly. This option is not recommended for simple setups. Please contact support - if you encounter problems while using this option. -
- -
- Enabling TLS also enables HTTP Strict Transport Security.
- This prevents downgrade attacks and cookie theft, but browsers will reject all future insecure connections on this hostname. -
- - - - - - - - - - -
Certificate: - -
- The certificate must be in PEM format. -
-
Private key: - -
-
- -
-
- - -
-
- Data Consistency Settings -
-
-
-

Relax constraints on consistency guarantees for specific operations - to enable higher performance and availability. -

-
- - - - -
-
- Allow repository pulls even if audit logging fails. -
- If enabled, failures to write to the audit log will fallback from - the database to the standard logger for registry pulls. -
-
-
-
-
- - -
-
- Time Machine -
-
-
-

Time machine keeps older copies of tags within a repository for the configured period - of time, after which they are garbage collected. This allows users to - revert tags to older images in case they accidentally pushed a broken image. It is - highly recommended to have time machine enabled, but it does take a bit more space - in storage. -

-
- - - - - - - - - - - - - - -
Allowed expiration periods: - -
- The expiration periods allowed for configuration. The default tag expiration *must* be in this list. -
-
Default expiration period: - -
- The default tag expiration period for all namespaces (users and organizations). Must be expressed in a duration string form: 30m, 1h, 1d, 2w. -
-
Allow users to select expiration: -
- Enable Expiration Configuration -
- If enabled, users will be able to select the tag expiration duration for the namespace(s) they - administrate, from the configured list of options. -
-
-
-
-
- - -
-
- redis -
-
-
-

A redis key-value store is required for real-time events and build logs.

-
- - - - - - - - - - - - - - -
Redis Hostname: - -
Redis port: - -
- Access to this port and hostname must be allowed from all hosts running - the enterprise registry -
-
Redis password: - -
-
-
- - -
-
- Registry Storage -
-
-
-

- Registry images can be stored either locally or in a remote storage system. - A remote storage system is required for high-availability systems. -

- -
- Enable Storage Replication -
- If enabled, replicates storage to other regions. See documentation for more information. -
-
- -
- - - - - - - - - - - - - - - - - - - - - -
Location ID: - -
- {{ sc.location }} -
-
- {{ storageConfigError[$index].location }} -
- -
Set Default: -
- Replicate to storage engine by default -
-
Storage Engine: - - -
- {{ storageConfigError[$index].engine }} -
-
{{ field.title }}: - - - - {{ field.placeholder }} - - -
- -
-
- {{ field.help_text }} -
-
- See Documentation for more information -
-
-
- - -
-
-
- - -
-
- Action Log Rotation and Archiving -
-
-
-

- All actions performed in are automatically logged. These logs are stored in a database table, which can become quite large. - Enabling log rotation and archiving will move all logs older than 30 days into storage. -

-
-
- Enable Action Log Rotation -
- - - - - - - - - - -
Storage location: - -
- The storage location in which to place archived action logs. Logs will only be archived to this single location. -
-
Storage path: - -
- The path under the configured storage engine in which to place the archived logs in JSON form. -
-
-
- - -
-
- Security Scanner -
-
-
-

If enabled, all images pushed to Quay will be scanned via the external security scanning service, with vulnerability information available in the UI and API, as well - as async notification support. -

-
- -
- Enable Security Scanning -
-
- A scanner compliant with the Quay Security Scanning API must be running to use this feature. Documentation on running Clair can be found at Running Clair Security Scanner. -
- - - - - - - - - - -
Authentication Key: - -
- The security scanning service requires an authorized service key to speak to Quay. Once setup, the key - can be managed in the Service Keys panel under the Super User Admin Panel. -
-
Security Scanner Endpoint: - -
- The HTTP URL at which the security scanner is running. -
-
- Is the security scanner behind a domain signed with a self-signed TLS certificate? If so, please make sure to register your SSL CA in the custom certificates panel above. -
-
-
-
- - -
-
- Application Registry -
-
-
-

If enabled, an additional registry API will be available for managing applications (Kubernetes manifests, Helm charts) via the App Registry specification. A great place to get started is to install the Helm Registry Plugin. -

- -
- Enable App Registry -
-
-
- - -
-
- BitTorrent-based download -
-
-
-

If enabled, all images in the registry can be downloaded using the quayctl tool via the BitTorrent protocol. A JWT-compatible BitTorrent tracker such as Chihaya must be run. -

- -
- Enable BitTorrent downloads -
- - - - - - -
Announce URL: - -
- The HTTP URL at which the torrents should be announced. A JWT-compatible tracker such as Chihaya must be run to ensure proper security. Documentation on running Chihaya with - this support can be found at Running Chihaya for Quay Enterprise. -
-
-
-
- - -
-
- rkt Conversion -
-
-
-

If enabled, all images in the registry can be fetched via rkt fetch or any other AppC discovery-compliant implementation.

-
- -
- Enable ACI Conversion -
- -
- Documentation on generating these keys can be found at Generating ACI Signing Keys. -
- - - - - - - - - - - - - - -
GPG2 Public Key File: - -
- The certificate must be in PEM format. -
-
GPG2 Private Key File: - -
GPG2 Private Key Name: - -
-
-
- - -
-
- E-mail -
-
-
-

Valid e-mail server configuration is required for notification e-mails and the ability of - users to reset their passwords.

-
- -
- Enable E-mails -
- - - - - - - - - - - - - - - - - - - - - - - -
SMTP Server: - > -
SMTP Server Port: - -
TLS: -
- Require TLS -
-
Mail Sender: - -
- E-mail address from which all e-mails are sent. If not specified, - support@quay.io will be used. -
-
Authentication: -
- Requires Authentication -
- - - - - - - - - - -
Username: - -
Password: - -
-
-
-
- - -
-
- Internal Authentication -
-
-
-

- Authentication for the registry can be handled by either the registry itself, LDAP, Keystone, or external JWT endpoint. -

-

- Additional external authentication providers (such as GitHub) can be used in addition for login into the UI. -

-
- -
-
- It is highly recommended to require encrypted client passwords. External passwords used in the Docker client will be stored in plaintext! - Enable this requirement now. -
- -
- Note: The "Require Encrypted Client Passwords" feature is currently enabled which will - prevent passwords from being saved as plaintext by the Docker client. -
-
- - - - - - - - - - - - - - - - - - - -
Authentication: - -
Team synchronization: -
- Enable Team Synchronization Support -
-
- If enabled, organization administrators who are also superusers can set teams to have their membership synchronized with a backing group in {{ config.AUTHENTICATION_TYPE }}. -
-
Resynchronization duration: - -
- The duration before a team must be re-synchronized. Must be expressed in a duration string form: 30m, 1h, 1d. -
-
Self-service team syncing setup: -
If enabled, this feature will allow *any organization administrator* to read the membership of any {{ config.AUTHENTICATION_TYPE }} group.
-
- Allow non-superusers to enable and manage team syncing -
-
- If enabled, non-superusers will be able to enable and manage team sycning on teams under organizations in which they are administrators. -
-
- - - - - - - - - - - - - - - - - - - - - - - -
Keystone API Version: - -
Keystone Authentication URL: - -
- The URL (starting with http or https) of the Keystone Server endpoint for auth. -
-
Keystone Administrator Username: - -
- The username for the Keystone admin. -
-
Keystone Administrator Password: - -
- The password for the Keystone admin. -
-
Keystone Administrator Tenant: - -
- The tenant (project/group) that contains the administrator user. -
-
- - -
- JSON Web Token authentication allows your organization to provide an HTTP endpoint that - verifies user credentials on behalf of . -
- Documentation - on the API required can be found here: https://github.com/coreos/jwt-auth-example. -
- - - - - - - - - - - - - - - - - - - - - - -
Authentication Issuer: - -
- The id of the issuer signing the JWT token. Must be unique to your organization. -
-
Public Key: - -
- A certificate containing the public key portion of the key pair used to sign - the JSON Web Tokens. This file must be in PEM format. -
-
User Verification Endpoint: - -
- The URL (starting with http or https) on the JWT authentication server for verifying username and password credentials. -
- -
- Credentials will be sent in the Authorization header as Basic Auth, and this endpoint should return 200 OK on success (or a 4** otherwise). -
-
User Query Endpoint: - -
- The URL (starting with http or https) on the JWT authentication server for looking up - users based on a prefix query. This is optional. -
- -
- The prefix query will be sent as a query parameter with name query. -
-
User Lookup Endpoint: - -
- The URL (starting with http or https) on the JWT authentication server for looking up - a user by username or email address. -
- -
- The username or email address will be sent as a query parameter with name username. -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
LDAP URI: - -
- The full LDAP URI, including the ldap:// or ldaps:// prefix. -
-
Base DN: - -
- A Distinguished Name path which forms the base path for looking up all LDAP records. -
-
- Example: dc=my,dc=domain,dc=com -
-
User Relative DN: - -
- A Distinguished Name path which forms the base path for looking up all user LDAP records, - relative to the Base DN defined above. -
-
- Example: ou=employees -
-
Secondary User Relative DNs: - -
- A list of Distinguished Name path(s) which forms the secondary base path(s) for - looking up all user LDAP records, relative to the Base DN defined above. These path(s) - will be tried if the user is not found via the primary relative DN. -
-
- Example: [ou=employees] -
-
Administrator DN: -
- The Distinguished Name for the Administrator account. This account must be able to login and view the records for all user accounts. -
-
- Example: uid=admin,ou=employees,dc=my,dc=domain,dc=com -
-
Administrator DN Password: -
- Note: This will be stored in - plaintext inside the config.yaml, so setting up a dedicated account or using - a password hash is highly recommended. -
- -
- The password for the Administrator DN. -
-
UID Attribute: - -
- The name of the property field in your LDAP user records that stores your - users' username. Typically "uid". -
-
Mail Attribute: - -
- The name of the property field in your LDAP user records that stores your - users' e-mail address(es). Typically "mail". -
-
Custom TLS Certificate: - -
- If specified, the certificate (in PEM format) for the LDAP TLS connection. -
-
Allow insecure: -
- Allow fallback to non-TLS connections -
-
- If enabled, LDAP will fallback to insecure non-TLS connections if TLS does not succeed. -
-
-
-
- -
-
- External Authorization (OAuth) -
-
- -
-
- GitHub (Enterprise) Authentication -
-
-
-

- If enabled, users can use GitHub or GitHub Enterprise to authenticate to the registry. -

-

- Note: A registered GitHub (Enterprise) OAuth application is required. - View instructions on how to - - Create an OAuth Application in GitHub - -

-
- -
- Enable GitHub Authentication -
- -
- Warning: This provider is not bound to your {{ config.AUTHENTICATION_TYPE }} authentication. Logging in via this provider will create a -only user, which is not the recommended approach. It is highly recommended to choose a "Binding Field" below. -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
GitHub: - -
GitHub Endpoint: - - -
- The GitHub Enterprise endpoint. Must start with http:// or https://. -
-
OAuth Client ID: - - -
OAuth Client Secret: - - -
Organization Filtering: -
- Restrict By Organization Membership -
- -
- If enabled, only members of specified GitHub - Enterprise organizations will be allowed to login via GitHub - Enterprise. -
- - - -
Binding Field: - -
- If selected, when a user logs in via this provider, they will be automatically bound to their user in {{ config.AUTHENTICATION_TYPE }} by matching the selected field from the provider to the associated user in {{ config.AUTHENTICATION_TYPE }}. -
-
- For example, selecting Subject here with a backing authentication system of LDAP means that a user logging in via this provider will also be bound to their user in LDAP by username. -
-
- If none selected, a user unique to will be created on initial login with this provider. This is not the recommended setup. -
-
-
-
- - -
-
- Google Authentication -
-
-
-

- If enabled, users can use Google to authenticate to the registry. -

-

- Note: A registered Google OAuth application is required. - Visit the - - Google Developer Console - - to register an application. -

-
- -
- Enable Google Authentication -
- -
- Warning: This provider is not bound to your {{ config.AUTHENTICATION_TYPE }} authentication. Logging in via this provider will create a -only user, which is not the recommended approach. It is highly recommended to choose a "Binding Field" below. -
- - - - - - - - - - - - - - -
OAuth Client ID: - - -
OAuth Client Secret: - - -
Binding Field: - -
- If selected, when a user logs in via this provider, they will be automatically bound to their user in {{ config.AUTHENTICATION_TYPE }} by matching the selected field from the provider to the associated user in {{ config.AUTHENTICATION_TYPE }}. -
-
- For example, selecting Subject here with a backing authentication system of LDAP means that a user logging in via this provider will also be bound to their user in LDAP by username. -
-
- If none selected, a user unique to will be created on initial login with this provider. This is not the recommended setup. -
-
-
-
- - -
-
- - {{ config[provider]['SERVICE_NAME'] || (getOIDCProviderId(provider) + ' Authentication') }} - (Delete) -
-
-
- Warning: This OIDC provider is not bound to your {{ config.AUTHENTICATION_TYPE }} authentication. Logging in via this provider will create a -only user, which is not the recommended approach. It is highly recommended to choose a "Binding Field" below. -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Service ID: - {{ getOIDCProviderId(provider) }} -
OIDC Server: - - -
- The URL of an OIDC-compliant server. -
-
Client ID: - -
Client Secret: - -
Service Name: - - -
- The user friendly name to display for the service on the login page. -
-
Service Icon (optional): - - -
- If specified, the icon to display for this login service on the login page. Can be either a URL to an icon or a CSS class name from Font Awesome -
-
Binding Field: - -
- If selected, when a user logs in via this OIDC provider, they will be automatically bound to their user in {{ config.AUTHENTICATION_TYPE }} by matching the selected field from the OIDC provider to the associated user in {{ config.AUTHENTICATION_TYPE }}. -
-
- For example, selecting Subject here with a backing authentication system of LDAP means that a user logging in via this OIDC provider will also be bound to their user in LDAP by username. -
-
- If none selected, a user unique to will be created on initial login with this OIDC provider. This is not the recommended setup. -
-
Login Scopes: - -
- If specified, the scopes to send to the OIDC provider when performing the login flow. Note that, if specified, these scopes will - override those set by default, so this list must include a scope for OpenID Connect - (typically the openid scope) or this provider will fail. -
-
-
-

Callback URLs for this service:

-
    -
  • {{ mapped.TLS_SETTING == 'none' ? 'http' : 'https' }}://{{ config.SERVER_HOSTNAME || '(configure server hostname)' }}/oauth2/{{ getOIDCProviderId(provider).toLowerCase() }}/callback
  • -
  • {{ mapped.TLS_SETTING == 'none' ? 'http' : 'https' }}://{{ config.SERVER_HOSTNAME || '(configure server hostname)' }}/oauth2/{{ getOIDCProviderId(provider).toLowerCase() }}/callback/attach
  • -
  • {{ mapped.TLS_SETTING == 'none' ? 'http' : 'https' }}://{{ config.SERVER_HOSTNAME || '(configure server hostname)' }}/oauth2/{{ getOIDCProviderId(provider).toLowerCase() }}/callback/cli
  • -
-
-
-
- - - Add OIDC Provider - What is OIDC? -
-
- - -
-
- Access Settings -
-
-
-

Various settings around access and authentication to the registry.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Basic Credentials Login: -
- Login to User Interface via credentials -
-
-
- Login to User Interface via credentials must be enabled. Click here to enable. -
-
- Login to User Interface via credentials is enabled (requires at least one OIDC provider to disable) -
-
-
- If enabled, users will be able to login to the user interface via their username and password credentials. -
-
- If disabled, users will only be able to login to the user interface via one of the configured External Authentication providers. -
-
External Application tokens -
- Allow external application tokens -
-
- If enabled, users will be able to generate external application tokens for use on the Docker and rkt CLI. Note - that these tokens will not be required unless "App Token" is chosen as the Internal Authentication method above. -
-
External application token expiration - -
- The expiration time for user generated external application tokens. If none, tokens will never expire. -
-
Anonymous Access: -
- Enable Anonymous Access -
-
- If enabled, public repositories and search can be accessed by anyone that can - reach the registry, even if they are not authenticated. Disable to only allow - authenticated users to view and pull "public" resources. -
-
User Creation: -
- Enable Open User Creation -
-
- If enabled, user accounts can be created by anyone (unless restricted below to invited users). - Users can always be created in the users panel in this superuser tool, even if this feature is disabled. -
-
Invite-only User Creation: -
- Enable Invite-only User Creation -
-
- If enabled, user accounts can only be created when a user has been invited, by e-mail address, to join a team. - Users can always be created in the users panel in this superuser tool, even if this feature is enabled. -
-
Encrypted Client Password: -
- Require Encrypted Client Passwords -
-
- If enabled, users will not be able to login from the Docker command - line with a non-encrypted password and must generate an encrypted - password to use. -
-
- This feature is highly recommended for setups with external authentication, as Docker currently stores passwords in plaintext on user's machines. -
-
Prefix username autocompletion: -
- Allow prefix username autocompletion -
-
- If disabled, autocompletion for users will only match on exact usernames. -
-
Team Invitations: -
- Require Team Invitations -
-
- If enabled, when adding a new user to a team, they will receive an invitation to join the team, with the option to decline. - Otherwise, users will be immediately part of a team when added by a team administrator. -
-
-
-
- - -
-
- Dockerfile Build Support -
-
-
- If enabled, users can submit Dockerfiles to be built and pushed by . -
- -
- Enable Dockerfile Build -
- -
- Note: Build workers are required for this feature. - See Adding Build Workers for instructions on how to setup build workers. -
-
-
- - -
-
- GitHub (Enterprise) Build Triggers -
-
-
-

- If enabled, users can setup GitHub or GitHub Enterprise triggers to invoke Registry builds. -

-

- Note: A registered GitHub (Enterprise) OAuth application (separate from GitHub Authentication) is required. - View instructions on how to - - Create an OAuth Application in GitHub - -

-
- -
- Enable GitHub Triggers -
- - - - - - - - - - - - - - - - - - -
GitHub: - -
GitHub Endpoint: - - -
- The GitHub Enterprise endpoint. Must start with http:// or https://. -
-
OAuth Client ID: - - -
OAuth Client Secret: - - -
-
-
- - -
-
- BitBucket Build Triggers -
-
-
-

- If enabled, users can setup BitBucket triggers to invoke Registry builds. -

-

- Note: A registered BitBucket OAuth application is required. - View instructions on how to - - Create an OAuth Application in BitBucket - -

-
- -
- Enable BitBucket Triggers -
- - - - - - - - - - -
OAuth Consumer Key: - - -
OAuth Consumer Secret: - - -
-
-
- - -
-
- GitLab Build Triggers -
-
-
-

- If enabled, users can setup GitLab triggers to invoke Registry builds. -

-

- Note: A registered GitLab OAuth application is required. - Visit the - - GitLab applications admin panel - - to create a new application. -

-

The callback URL to use is:   - {{ config.PREFERRED_URL_SCHEME || 'http' }}://{{ config.SERVER_HOSTNAME || 'localhost' }}/oauth2/gitlab/callback/trigger -

-
- -
- Enable GitLab Triggers -
- - - - - - - - - - - - - - - - - - -
GitLab: - -
GitLab Endpoint: - - -
- The GitLab Enterprise endpoint. Must start with http:// or https://. -
-
Application Id: - - -
Secret: - - -
-
-
- - - - -
- - -
- - - - -
-
diff --git a/config_app/js/core-config-setup/config-setup-tool.html b/config_app/js/core-config-setup/config-setup-tool.html index eed17afce..a246e46e8 100644 --- a/config_app/js/core-config-setup/config-setup-tool.html +++ b/config_app/js/core-config-setup/config-setup-tool.html @@ -1630,9 +1630,9 @@
diff --git a/config_app/js/core-config-setup/core-config-setup.js b/config_app/js/core-config-setup/core-config-setup.js index e55fb45e2..1cf5ea7f9 100644 --- a/config_app/js/core-config-setup/core-config-setup.js +++ b/config_app/js/core-config-setup/core-config-setup.js @@ -413,12 +413,12 @@ angular.module("quay-config") } }; - $scope.saveConfiguration = function() { + $scope.generateConfigTarball = function() { $scope.savingConfiguration = true; // Make sure to note that fully verified setup is completed. We use this as a signal // in the setup tool. - $scope.config['SETUP_COMPLETE'] = true; + // $scope.config['SETUP_COMPLETE'] = true; var data = { 'config': $scope.config, @@ -432,9 +432,14 @@ angular.module("quay-config") authPassword = null; }); - ApiService.scUpdateConfig(data).then(function(resp) { + // 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) + ApiService.scGetConfigTarball(null, null, null, null, true).then(function(resp) { authPassword = null; + FileSaver.saveAs(resp, 'quay-config.tar.gz'); + $scope.savingConfiguration = false; $scope.mapped.$hasChanges = false; diff --git a/config_app/js/services/api-service.js b/config_app/js/services/api-service.js index 5163f1cba..2a36bf35b 100644 --- a/config_app/js/services/api-service.js +++ b/config_app/js/services/api-service.js @@ -212,12 +212,20 @@ angular.module('quay-config').factory('ApiService', ['Restangular', '$q', 'UtilS var urlPath = path['x-path']; // Add the operation itself. - apiService[operationName] = function(opt_options, opt_parameters, opt_background, opt_forceget) { + apiService[operationName] = function(opt_options, opt_parameters, opt_background, opt_forceget, opt_blobresp) { var one = Restangular.one(buildUrl(urlPath, opt_parameters)); - if (opt_background) { - one.withHttpConfig({ - 'ignoreLoadingBar': true - }); + + if (opt_background || opt_blobresp) { + let httpConfig = {}; + + if (opt_background) { + httpConfig['ignoreLoadingBar'] = true; + } + if (opt_blobresp) { + httpConfig['responseType'] = 'blob'; + } + + one.withHttpConfig(httpConfig); } var opObj = one[opt_forceget ? 'get' : 'custom' + method.toUpperCase()](opt_options); diff --git a/util/config/validators/validate_storage.py b/util/config/validators/validate_storage.py index 4aec66aae..3e3de74ee 100644 --- a/util/config/validators/validate_storage.py +++ b/util/config/validators/validate_storage.py @@ -1,5 +1,5 @@ from storage import get_storage_driver -from util.config.validators import BaseValidator, ConfigValidationException, LocalStorageConfigValidationException +from util.config.validators import BaseValidator, ConfigValidationException class StorageValidator(BaseValidator):