diff --git a/config_app/config_endpoints/api/tar_config_loader.py b/config_app/config_endpoints/api/tar_config_loader.py index d235dad3b..d7e41d446 100644 --- a/config_app/config_endpoints/api/tar_config_loader.py +++ b/config_app/config_endpoints/api/tar_config_loader.py @@ -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') diff --git a/config_app/config_util/config/__init__.py b/config_app/config_util/config/__init__.py index d32c159d8..018d5cc8c 100644 --- a/config_app/config_util/config/__init__.py +++ b/config_app/config_util/config/__init__.py @@ -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() diff --git a/config_app/config_util/config/inmemoryprovider.py b/config_app/config_util/config/inmemoryprovider.py new file mode 100644 index 000000000..750cf1aed --- /dev/null +++ b/config_app/config_util/config/inmemoryprovider.py @@ -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() + diff --git a/config_app/js/components/load-config/load-config.component.ts b/config_app/js/components/load-config/load-config.component.ts index 892958e03..a4d745af2 100644 --- a/config_app/js/components/load-config/load-config.component.ts +++ b/config_app/js/components/load-config/load-config.component.ts @@ -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; } } \ No newline at end of file diff --git a/config_app/js/components/load-config/load-config.html b/config_app/js/components/load-config/load-config.html index 3dd982f0d..bc1aee793 100644 --- a/config_app/js/components/load-config/load-config.html +++ b/config_app/js/components/load-config/load-config.html @@ -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']">