import base64 import json from scheduler.resources import Resource from scheduler.exceptions import KubeHTTPException, KubeException class Secret(Resource): def get(self, namespace, name=None, **kwargs): """ Fetch a single Secret or a list """ url = '/namespaces/{}/secrets' args = [namespace] if name is not None: args.append(name) url += '/{}' message = 'get Secret "{}" in Namespace "{}"' else: message = 'get Secrets in Namespace "{}"' url = self.api(url, *args) response = self.http_get(url, params=self.query_params(**kwargs)) if self.unhealthy(response.status_code): args.reverse() # error msg is in reverse order raise KubeHTTPException(response, message, *args) # return right away if it is a list if name is None: return response # decode the base64 data secrets = response.json() for key, value in secrets['data'].items(): if value is None: secrets['data'][key] = '' continue value = base64.b64decode(value) value = value if isinstance(value, bytes) else bytes(str(value), 'UTF-8') secrets['data'][key] = value.decode(encoding='UTF-8') # tell python-requests it actually hasn't consumed the data response._content = bytes(json.dumps(secrets), 'UTF-8') return response def manifest(self, namespace, name, data, secret_type='Opaque', labels={}): secret_types = ['Opaque', 'kubernetes.io/dockerconfigjson'] if secret_type not in secret_types: raise KubeException('{} is not a supported secret type. Use one of the following: '.format(secret_type, ', '.join(secret_types))) # noqa manifest = { 'kind': 'Secret', 'apiVersion': 'v1', 'metadata': { 'name': name, 'namespace': namespace, 'labels': { 'app': namespace, 'heritage': 'deis' } }, 'type': secret_type, 'data': {} } # add in any additional label info manifest['metadata']['labels'].update(labels) for key, value in data.items(): if value is None: manifest['data'].update({key: ''}) continue value = value if isinstance(value, bytes) else bytes(str(value), 'UTF-8') item = base64.b64encode(value).decode(encoding='UTF-8') manifest['data'].update({key: item}) return manifest def create(self, namespace, name, data, secret_type='Opaque', labels={}): manifest = self.manifest(namespace, name, data, secret_type, labels) url = self.api("/namespaces/{}/secrets", namespace) response = self.http_post(url, json=manifest) if self.unhealthy(response.status_code): raise KubeHTTPException( response, 'failed to create Secret "{}" in Namespace "{}"', name, namespace ) return response def update(self, namespace, name, data, secret_type='Opaque', labels={}): manifest = self.manifest(namespace, name, data, secret_type, labels) url = self.api("/namespaces/{}/secrets/{}", namespace, name) response = self.http_put(url, json=manifest) if self.unhealthy(response.status_code): raise KubeHTTPException( response, 'failed to update Secret "{}" in Namespace "{}"', name, namespace ) return response def delete(self, namespace, name): url = self.api("/namespaces/{}/secrets/{}", namespace, name) response = self.http_delete(url) if self.unhealthy(response.status_code): raise KubeHTTPException( response, 'delete Secret "{}" in Namespace "{}"', name, namespace ) return response