diff --git a/util/config/provider/baseprovider.py b/util/config/provider/baseprovider.py index c833c2323..e5af29fa4 100644 --- a/util/config/provider/baseprovider.py +++ b/util/config/provider/baseprovider.py @@ -88,6 +88,16 @@ class BaseProvider(object): """ Writes the given contents to the config override volumne, with the given filename. """ raise NotImplementedError + def remove_volume_file(self, filename): + """ Removes the config override volume file with the given filename. """ + raise NotImplementedError + + def list_volume_directory(self, path): + """ Returns a list of strings representing the names of the files found in the config override + directory under the given path. If the path doesn't exist, returns None. + """ + raise NotImplementedError + def save_volume_file(self, filename, flask_file): """ Saves the given flask file to the config override volume, with the given filename. diff --git a/util/config/provider/fileprovider.py b/util/config/provider/fileprovider.py index 099c5c3fd..f59c495f1 100644 --- a/util/config/provider/fileprovider.py +++ b/util/config/provider/fileprovider.py @@ -59,6 +59,17 @@ class FileConfigProvider(BaseProvider): return filepath + def remove_volume_file(self, filename): + filepath = os.path.join(self.config_volume, filename) + os.remove(filepath) + + def list_volume_directory(self, path): + dirpath = os.path.join(self.config_volume, path) + if not os.path.exists(dirpath): + return None + + return os.listdir(dirpath) + def save_volume_file(self, filename, flask_file): filepath = os.path.join(self.config_volume, filename) try: diff --git a/util/config/provider/k8sprovider.py b/util/config/provider/k8sprovider.py index 334cf4044..7552eb839 100644 --- a/util/config/provider/k8sprovider.py +++ b/util/config/provider/k8sprovider.py @@ -55,53 +55,56 @@ class KubernetesConfigProvider(FileConfigProvider): except IOError as ioe: raise CannotWriteConfigException(str(ioe)) - def save_volume_file(self, filename, flask_file): - filepath = super(KubernetesConfigProvider, self).save_volume_file(filename, flask_file) + def remove_volume_file(self, filename): + super(KubernetesConfigProvider, self).remove_volume_file(filename) try: - with open(filepath, 'r') as f: - self._update_secret_file(filename, f.read()) + self._update_secret_file(filename, None) except IOError as ioe: raise CannotWriteConfigException(str(ioe)) + def save_volume_file(self, filename, flask_file): + filepath = super(KubernetesConfigProvider, self).save_volume_file(filename, flask_file) + with open(filepath, 'r') as f: + self.write_volume_file(filename, f.read()) + def _assert_success(self, response): if response.status_code != 200: logger.error('Kubernetes API call failed with response: %s => %s', response.status_code, response.text) raise CannotWriteConfigException('Kubernetes API call failed: %s' % response.text) - def _update_secret_file(self, filename, value): + def _update_secret_file(self, filename, value=None): # Check first that the namespace for Quay Enterprise exists. If it does not, report that # as an error, as it seems to be a common issue. namespace_url = 'namespaces/%s' % (QE_NAMESPACE) response = self._execute_k8s_api('GET', namespace_url) - if response.status_code != 200: + if response.status_code / 100 != 2: msg = 'A Kubernetes namespace with name `%s` must be created to save config' % QE_NAMESPACE raise CannotWriteConfigException(msg) - # Save the secret to the namespace. - secret_data = {} - secret_data[filename] = base64.b64encode(value) - - data = { - "kind": "Secret", - "apiVersion": "v1", - "metadata": { - "name": QE_CONFIG_SECRET - }, - "data": secret_data - } - + # Check if the secret exists. If not, then we create an empty secret and then update the file + # inside. secret_url = 'namespaces/%s/secrets/%s' % (QE_NAMESPACE, QE_CONFIG_SECRET) secret = self._lookup_secret() - if not secret: - self._assert_success(self._execute_k8s_api('POST', secret_url, data)) - return + if secret is None: + self._assert_success(self._execute_k8s_api('POST', secret_url, { + "kind": "Secret", + "apiVersion": "v1", + "metadata": { + "name": QE_CONFIG_SECRET + }, + "data": {} + })) - if not 'data' in secret: - secret['data'] = {} + # Update the secret to reflect the file change. + secret['data'] = secret.get('data', {}) + + if value is not None: + secret['data'][filename] = base64.b64encode(value) + else: + secret['data'].pop(filename) - secret['data'][filename] = base64.b64encode(value) self._assert_success(self._execute_k8s_api('PUT', secret_url, secret))