Read tarball into in-memory config provider

This commit is contained in:
Sam Chow 2018-06-18 16:01:30 -04:00
parent 8aa18a29a8
commit bb2b28cd11
5 changed files with 83 additions and 9 deletions

View file

@ -1,4 +1,6 @@
import logging
import tarfile
import cStringIO
from flask import request, make_response
@ -17,9 +19,10 @@ class TarConfigLoader(ApiResource):
input_stream = request.stream
# since we're working with a tar file, shouldn't be larger than ~20KB, so just read the whole thing into mem
buf = input_stream.read(-1)
buf = input_stream.read()
config = tarfile.open(mode="r:gz", fileobj=cStringIO.StringIO(buf))
# TODO(sam): refactor config provider to accept a stream write to avoid loading into memory
config_provider.write_volume_file('test_tar.tar.gz', buf)
config_provider.load_from_tarball(config)
return make_response('OK')

View file

@ -1,9 +1,13 @@
from config_app.config_util.config.fileprovider import FileConfigProvider
from config_app.config_util.config.testprovider import TestConfigProvider
from config_app.config_util.config.inmemoryprovider import InMemoryProvider
def get_config_provider(config_volume, yaml_filename, py_filename, testing=False):
""" Loads and returns the config provider for the current environment. """
if True:
return InMemoryProvider()
if testing:
return TestConfigProvider()

View file

@ -0,0 +1,66 @@
import logging
import yaml
from config_app.config_util.config.baseprovider import BaseProvider
logger = logging.getLogger(__name__)
CONFIG_FILENAME = 'config.yaml'
class InMemoryProvider(BaseProvider):
def __init__(self):
self.files = {}
self.config = {}
@property
def provider_id(self):
return 'memory'
def update_app_config(self, app_config):
self.config = app_config
def get_config(self):
return self.config
def save_config(self, config_object):
raise Exception('Not implemented yet')
def config_exists(self):
raise Exception('Not implemented yet')
def volume_exists(self):
raise Exception('Not implemented yet')
def volume_file_exists(self, filename):
return filename in self.files
def get_volume_file(self, filename, mode='r'):
return self.files[filename]
def write_volume_file(self, filename, contents):
raise Exception('Not implemented yet')
def remove_volume_file(self, filename):
raise Exception('Not implemented yet')
def list_volume_directory(self, path):
return [ name for name in self.files ]
def save_volume_file(self, filename, flask_file):
raise Exception('Not implemented yet')
def requires_restart(self, app_config):
raise Exception('Not implemented yet')
def get_volume_path(self, directory, filename):
raise Exception('Not implemented yet')
def load_from_tarball(self, tarfile):
for tarinfo in tarfile.getmembers():
if tarinfo.isfile():
if tarinfo.name == CONFIG_FILENAME:
self.config = yaml.load(tarfile.extractfile(tarinfo.name).read())
else:
self.files[tarinfo.name] = tarfile.extractfile(tarinfo.name).read()

View file

@ -8,7 +8,7 @@ const styleUrl = require('./load-config.css');
styleUrls: [ styleUrl ],
})
export class LoadConfigComponent {
private isReady: boolean = false;
private readyToSubmit: boolean = false;
private uploadFunc: Function;
private state: 'load' | 'validate' = 'load';
@ -16,12 +16,12 @@ export class LoadConfigComponent {
}
private handleTarballSelected(files: File[], callback: Function) {
this.isReady = true;
this.readyToSubmit = true;
callback(true)
}
private handleTarballCleared() {
this.isReady = false;
this.readyToSubmit = false;
}
private uploadTarball() {
@ -30,7 +30,8 @@ export class LoadConfigComponent {
this.state = 'validate';
}
else {
this.apiService.errorDisplay('Could not upload configuration. Please reload the page and try again.\n' +
this.apiService.errorDisplay('Error loading configuration',
'Could not upload configuration. Please reload the page and try again.\n' +
'If this problem persists, please contact support')();
}
});
@ -42,7 +43,7 @@ export class LoadConfigComponent {
* @param files: files to upload
* @param uploadFiles: function to call to upload files
*/
private filesValidated(files, uploadFiles) {
private tarballValidatedByUploadBox(files, uploadFiles) {
this.uploadFunc = uploadFiles;
}
}

View file

@ -14,11 +14,11 @@
select-message="Select a previous configuration to modify. Must be in tar.gz format"
files-selected="$ctrl.handleTarballSelected(files, callback)"
files-cleared="$ctrl.handleFilesCleared()"
files-validated="$ctrl.filesValidated(files, uploadFiles)"
files-validated="$ctrl.tarballValidatedByUploadBox(files, uploadFiles)"
extensions="['application/gzip', '.gz']"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" ng-click="$ctrl.uploadTarball()" ng-disabled="!$ctrl.isReady">
<button type="button" class="btn btn-primary" ng-click="$ctrl.uploadTarball()" ng-disabled="!$ctrl.readyToSubmit">
Upload Configuration
</button>
</div>