예제 #1
0
파일: k8s_drain.py 프로젝트: hhue13/ansible
    def __init__(self, module):
        from ansible_collections.kubernetes.core.plugins.module_utils.common import (
            K8sAnsibleMixin, get_api_client)

        self._module = module
        self._k8s_ansible_mixin = K8sAnsibleMixin(module)
        self._k8s_ansible_mixin.client = get_api_client(module=self._module)

        self._k8s_ansible_mixin.module = self._module
        self._k8s_ansible_mixin.argspec = self._module.argument_spec
        self._k8s_ansible_mixin.check_mode = self._module.check_mode
        self._k8s_ansible_mixin.params = self._module.params
        self._k8s_ansible_mixin.fail_json = self._module.fail_json
        self._k8s_ansible_mixin.fail = self._module.fail_json
        self._k8s_ansible_mixin.exit_json = self._module.exit_json
        self._k8s_ansible_mixin.warn = self._module.warn
        self._k8s_ansible_mixin.warnings = []

        self._api_instance = core_v1_api.CoreV1Api(
            self._k8s_ansible_mixin.client.client)
        self._k8s_ansible_mixin.check_library_version()

        # delete options
        self._drain_options = module.params.get('delete_options', {})
        self._delete_options = None
        if self._drain_options.get('terminate_grace_period'):
            self._delete_options = {}
            self._delete_options.update({'apiVersion': 'v1'})
            self._delete_options.update({'kind': 'DeleteOptions'})
            self._delete_options.update({
                'gracePeriodSeconds':
                self._drain_options.get('terminate_grace_period')
            })

        self._changed = False
예제 #2
0
    def __init__(self, kubernetes_namespace):
        self.client = apps_v1_api.AppsV1Api()
        self.core_client = core_v1_api.CoreV1Api()

        self.kubernetes_config_map = KubernetesConfigMap()

        self.kubernetes_namespace = kubernetes_namespace
예제 #3
0
    def test_configmap_apis(self):
        client = api_client.ApiClient(configuration=self.config)
        api = core_v1_api.CoreV1Api(client)

        name = 'test-configmap-' + short_uuid()
        test_configmap = {
            "kind": "ConfigMap",
            "apiVersion": "v1",
            "metadata": {
                "name": name,
            },
            "data": {
                "config.json": "{\"command\":\"/usr/bin/mysqld_safe\"}",
                "frontend.cnf": "[mysqld]\nbind-address = 10.0.0.3\nport = 3306\n"
            }
        }

        resp = api.create_namespaced_config_map(
            body=test_configmap, namespace='default'
        )
        self.assertEqual(name, resp.metadata.name)

        resp = api.read_namespaced_config_map(
            name=name, namespace='default')
        self.assertEqual(name, resp.metadata.name)

        test_configmap['data']['config.json'] = "{}"
        resp = api.patch_namespaced_config_map(
            name=name, namespace='default', body=test_configmap)

        resp = api.delete_namespaced_config_map(
            name=name, body={}, namespace='default')

        resp = api.list_namespaced_config_map('default', pretty=True)
        self.assertEqual([], resp.items)
예제 #4
0
    def test_replication_controller_apis(self):
        client = api_client.ApiClient(configuration=self.config)
        api = core_v1_api.CoreV1Api(client)

        name = 'frontend-' + short_uuid()
        rc_manifest = {
            'apiVersion': 'v1',
            'kind': 'ReplicationController',
            'metadata': {'labels': {'name': name},
                         'name': name},
            'spec': {'replicas': 2,
                     'selector': {'name': name},
                     'template': {'metadata': {
                         'labels': {'name': name}},
                         'spec': {'containers': [{
                             'image': 'nginx',
                             'name': 'nginx',
                             'ports': [{'containerPort': 80,
                                        'protocol': 'TCP'}]}]}}}}

        resp = api.create_namespaced_replication_controller(
            body=rc_manifest, namespace='default')
        self.assertEqual(name, resp.metadata.name)
        self.assertEqual(2, resp.spec.replicas)

        resp = api.read_namespaced_replication_controller(
            name=name, namespace='default')
        self.assertEqual(name, resp.metadata.name)
        self.assertEqual(2, resp.spec.replicas)

        resp = api.delete_namespaced_replication_controller(
            name=name, body={}, namespace='default')
예제 #5
0
 def __init__(self, image, command, input_file_names=None, output_file_name=None):
     pod_name = str(uuid.uuid4())
     container_name = str(uuid.uuid4())
     self.body = {
         'apiVersion': 'v1', 'kind': 'Pod', 'metadata': {'name': pod_name},
         'spec': {
             'restartPolicy': 'Never',
             'containers': [
                 {
                     'name': container_name,
                     'image': image,
                     'command': ['/bin/sh', '-c'],
                     'args': [command]
                 }
             ]
         }
     }
     self.input_file_names = input_file_names
     self.output_file_name = output_file_name
     config.load_kube_config()
     self.core_v1 = core_v1_api.CoreV1Api()
     self.pod_name = self.body['metadata']['name']
     self.namespace = "default"
     self._succeeded = False
     self._started = False
예제 #6
0
    def _get_k8s_api_client(self):
        cluster_uuid = self.context["tenant"]["cluster"]
        cluster = self._get_cluster(cluster_uuid)
        cluster_template = self._get_cluster_template(
            cluster.cluster_template_id)
        key_file = None
        cert_file = None
        ca_certs = None
        if not cluster_template.tls_disabled:
            dir = self.context["ca_certs_directory"]
            key_file = cluster_uuid + ".key"
            key_file = os.path.join(dir, key_file)
            cert_file = cluster_uuid + ".crt"
            cert_file = os.path.join(dir, cert_file)
            ca_certs = cluster_uuid + "_ca.crt"
            ca_certs = os.path.join(dir, ca_certs)
        if hasattr(k8s_config, "ConfigurationObject"):
            # k8sclient < 4.0.0
            config = k8s_config.ConfigurationObject()
        else:
            config = k8s_config.Configuration()
        config.host = cluster.api_address
        config.ssl_ca_cert = ca_certs
        config.cert_file = cert_file
        config.key_file = key_file
        if hasattr(k8s_config, "ConfigurationObject"):
            # k8sclient < 4.0.0
            client = api_client.ApiClient(config=config)
        else:
            client = api_client.ApiClient(config)

        return core_v1_api.CoreV1Api(client)
예제 #7
0
def main():

    common.connect()

    api = core_v1_api.CoreV1Api()
    container = None
    name = None
    namespace = None

    name = os.environ.get('RD_CONFIG_NAME',
                          os.environ.get('RD_NODE_DEFAULT_NAME'))
    namespace = os.environ.get(
        'RD_CONFIG_NAMESPACE',
        os.environ.get('RD_NODE_DEFAULT_NAMESPACE', 'default'))

    if 'RD_NODE_DEFAULT_CONTAINER_NAME' in os.environ:
        container = os.environ.get('RD_NODE_DEFAULT_CONTAINER_NAME')
    else:
        core_v1 = client.CoreV1Api()
        response = core_v1.read_namespaced_pod_status(name=name,
                                                      namespace=namespace,
                                                      pretty="True")
        container = response.spec.containers[0].name

    log.debug("--------------------------")
    log.debug("Pod Name:  %s", name)
    log.debug("Namespace: %s", namespace)
    log.debug("Container: %s", container)
    log.debug("--------------------------")

    resp = None
    try:
        resp = api.read_namespaced_pod(name=name, namespace=namespace)
    except ApiException as e:
        if e.status != 404:
            log.exception("Unknown error:")
            exit(1)

    if not resp:
        log.error("Pod %s does not exist", name)
        exit(1)

    shell = os.environ.get('RD_CONFIG_SHELL')

    if 'RD_EXEC_COMMAND' in os.environ:
        command = os.environ['RD_EXEC_COMMAND']
    else:
        command = os.environ['RD_CONFIG_COMMAND']

    log.debug("Command: %s ", command)

    # calling exec and wait for response.
    exec_command = [shell, '-c', command]

    resp, error = common.run_interactive_command(name, namespace, container,
                                                 exec_command)

    if error:
        log.error("error running script")
        sys.exit(1)
예제 #8
0
    def test_portforward_http(self):
        client = api_client.ApiClient(configuration=self.config)
        api = core_v1_api.CoreV1Api(client)

        name = 'portforward-http-' + short_uuid()
        pod_manifest = {
            'apiVersion': 'v1',
            'kind': 'Pod',
            'metadata': {
                'name': name
            },
            'spec': {
                'containers': [{
                    'name': 'nginx',
                    'image': 'nginx',
                }]
            }
        }

        resp = api.create_namespaced_pod(body=pod_manifest,
                                         namespace='default')
        self.assertEqual(name, resp.metadata.name)
        self.assertTrue(resp.status.phase)

        while True:
            resp = api.read_namespaced_pod(name=name, namespace='default')
            self.assertEqual(name, resp.metadata.name)
            self.assertTrue(resp.status.phase)
            if resp.status.phase != 'Pending':
                break
            time.sleep(1)

        def kubernetes_create_connection(address, *args, **kwargs):
            dns_name = address[0]
            if isinstance(dns_name, bytes):
                dns_name = dns_name.decode()
            dns_name = dns_name.split(".")
            if len(dns_name) != 3 or dns_name[2] != "kubernetes":
                return socket_create_connection(address, *args, **kwargs)
            pf = portforward(api.connect_get_namespaced_pod_portforward,
                             dns_name[0],
                             dns_name[1],
                             ports=str(address[1]))
            return pf.socket(address[1])

        socket_create_connection = socket.create_connection
        try:
            socket.create_connection = kubernetes_create_connection
            response = urllib_request.urlopen('http://%s.default.kubernetes/' %
                                              name)
            html = response.read().decode('utf-8')
        finally:
            socket.create_connection = socket_create_connection

        self.assertEqual(response.code, 200)
        self.assertTrue('<h1>Welcome to nginx!</h1>' in html)

        resp = api.delete_namespaced_pod(name=name,
                                         body={},
                                         namespace='default')
예제 #9
0
    def __init__(self, kubernetes_namespace: KubernetesNamespace) -> None:
        self.client: apps_v1_api.AppsV1Api = apps_v1_api.AppsV1Api()
        self.core_client: core_v1_api.CoreV1Api = core_v1_api.CoreV1Api()

        self.kubernetes_config_map: KubernetesConfigMap = KubernetesConfigMap()

        self.kubernetes_namespace: KubernetesNamespace = kubernetes_namespace
def k8s_api():
    config.load_kube_config()
    c = Configuration()
    c.assert_hostname = False
    Configuration.set_default(c)
    core_v1 = core_v1_api.CoreV1Api()
    return core_v1
예제 #11
0
    def __init__(self, **kw):
        super(KubernetesRunner, self).__init__(**kw)

        config.load_kube_config()

        c = Configuration()
        c.assert_hostname = False
        Configuration.set_default(c)
        self._kclient = core_v1_api.CoreV1Api()

        _, active_context = config.list_kube_config_contexts()

        self._namespace = self._config.resman_opts.get("namespace", "default")

        self._base_pod_name = pu.sanitized_name(f"pod", self._config.wid)
        self._base_pod_name = self._base_pod_name.replace("_", "-")

        self._init_pod_name = pu.sanitized_name("init-pod", self._config.wid)
        self._init_pod_name = self._init_pod_name.replace("_", "-")

        self._vol_claim_name = f"{self._base_pod_name}-pvc"
        self._vol_size = self._config.resman_opts.get("volume_size", "500Mi")

        self._init_pod_created = False
        self._vol_claim_created = False
예제 #12
0
    def test_node_apis(self):
        client = api_client.ApiClient(configuration=self.config)
        api = core_v1_api.CoreV1Api(client)

        for item in api.list_node().items:
            node = api.read_node(name=item.metadata.name)
            self.assertTrue(len(node.metadata.labels) > 0)
            self.assertTrue(isinstance(node.metadata.labels, dict))
예제 #13
0
def main():
    config.load_kube_config()
    c = Configuration.get_default_copy()
    c.assert_hostname = False
    Configuration.set_default(c)
    core_v1 = core_v1_api.CoreV1Api()

    portforward_commands(core_v1)
예제 #14
0
 def get_api(self):
     configuration = client.Configuration()
     configuration.host = self.url
     configuration.verify_ssl = False
     configuration.api_key = {"authorization": "Bearer " + self.token}
     c = api_client.ApiClient(configuration=configuration)
     api = core_v1_api.CoreV1Api(c)
     return api
def main():
    config.load_kube_config()
    c = Configuration()
    c.assert_hostname = False
    Configuration.set_default(c)
    core_v1 = core_v1_api.CoreV1Api()

    exec_commands(core_v1)
예제 #16
0
    def setUp(self):
        log.setLevel("CRITICAL")
        config.load_kube_config()

        c = Configuration()
        c.assert_hostname = False
        Configuration.set_default(c)
        self._kclient = core_v1_api.CoreV1Api()

        _, active_context = config.list_kube_config_contexts()
예제 #17
0
def main():
    config.load_kube_config()
    try:
        c = Configuration().get_default_copy()
    except AttributeError:
        c = Configuration()
        c.assert_hostname = False
    Configuration.set_default(c)
    core_v1 = core_v1_api.CoreV1Api()

    exec_commands(core_v1)
예제 #18
0
    def __init__(self, session):
        try:
            self.session = literal_eval(session)
        except Exception:
            self.session = session

        if Utils.is_gcp():
            GKEConfiguration().set_config()
        else:
            LocalKubernetesConfiguration().set_config()
        self.core_api = core_v1_api.CoreV1Api()
def main():
    logger = create_logger(PurePath(__file__).stem)

    config.load_incluster_config()

    configuration = Configuration()
    configuration.verify_ssl = False
    configuration.assert_hostname = False
    urllib3.disable_warnings()
    Configuration.set_default(configuration)

    api = core_v1_api.CoreV1Api()
    label_selector = getenv('LABEL_SELECTOR', 'role=greyhole')
    namespace = getenv('NAMESPACE', 'storage')
    command_switch = getenv('COMMAND_SWITCH', '')

    k8s_response = api.list_namespaced_pod(namespace=namespace,
                                           label_selector=label_selector)

    logger.info(f'ENV Commands {label_selector} {namespace} {command_switch}')
    logger.debug(f'{k8s_response}')

    for pod in k8s_response.items:
        name = pod.metadata.name

        k8s_response = api.read_namespaced_pod(name=name, namespace=namespace)

        exec_command = ['/bin/sh', '-c']

        if command_switch.lower() == 'monthly':
            exec_command.append('greyhole --fsck --checksums')
        elif command_switch.lower() == 'weekly':
            exec_command.append(
                'greyhole --fsck --dont-walk-metadata-store --disk-usage-report'
            )
        elif command_switch.lower() == 'daily':
            exec_command.append(
                'greyhole --fsck --if-conf-changed --dont-walk-metadata-store')
        else:
            exec_command.append('greyhole --process-spool --keepalive')

        k8s_response = stream(api.connect_get_namespaced_pod_exec,
                              name,
                              namespace,
                              command=exec_command,
                              stderr=True,
                              stdin=False,
                              stdout=True,
                              tty=False)

        logger.info(f'Cleanup {name}: {k8s_response}')

    logger.info(f'Successfully executed cron job')
예제 #20
0
    def test_service_apis(self):
        client = api_client.ApiClient(configuration=self.config)
        api = core_v1_api.CoreV1Api(client)

        name = 'frontend-' + short_uuid()
        service_manifest = {
            'apiVersion': 'v1',
            'kind': 'Service',
            'metadata': {
                'labels': {
                    'name': name
                },
                'name': name,
                'resourceversion': 'v1'
            },
            'spec': {
                'ports': [{
                    'name': 'port',
                    'port': 80,
                    'protocol': 'TCP',
                    'targetPort': 80
                }],
                'selector': {
                    'name': name
                }
            }
        }

        resp = api.create_namespaced_service(body=service_manifest,
                                             namespace='default')
        self.assertEqual(name, resp.metadata.name)
        self.assertTrue(resp.status)

        resp = api.read_namespaced_service(name=name, namespace='default')
        self.assertEqual(name, resp.metadata.name)
        self.assertTrue(resp.status)

        service_manifest['spec']['ports'] = [{
            'name': 'new',
            'port': 8080,
            'protocol': 'TCP',
            'targetPort': 8080
        }]
        resp = api.patch_namespaced_service(body=service_manifest,
                                            name=name,
                                            namespace='default')
        self.assertEqual(2, len(resp.spec.ports))
        self.assertTrue(resp.status)

        resp = api.delete_namespaced_service(name=name,
                                             body={},
                                             namespace='default')
예제 #21
0
def verify_pod_exists(name, namespace):
    """Verify pod exists."""
    api = core_v1_api.CoreV1Api()
    resp = None
    try:
        resp = api.read_namespaced_pod(name=name, namespace=namespace)
    except ApiException as e:
        if e.status != 404:
            log.exception("Unknown error:")
            exit(1)
    if not resp:
        log.error("Pod %s does not exist", name)
        exit(1)
예제 #22
0
def copy_file(name,
              namespace,
              container,
              source_file,
              destination_path,
              destination_file_name,
              stdout=False):
    api = core_v1_api.CoreV1Api()

    # Copying file client -> pod
    exec_command = ['tar', 'xvf', '-', '-C', '/']
    resp = stream(api.connect_get_namespaced_pod_exec,
                  name,
                  namespace,
                  command=exec_command,
                  container=container,
                  stderr=False,
                  stdin=True,
                  stdout=False,
                  tty=False,
                  _preload_content=False)

    with TemporaryFile() as tar_buffer:
        with tarfile.open(fileobj=tar_buffer, mode='w') as tar:
            tar.add(name=source_file,
                    arcname=destination_path + "/" + destination_file_name)

        tar_buffer.seek(0)
        commands = []
        commands.append(tar_buffer.read())

        while resp.is_open():
            resp.update(timeout=1)

            if resp.peek_stdout():
                if stdout:
                    log.info("%s" % resp.read_stdout())
            if resp.peek_stderr():
                log.error("ERROR: %s" % resp.read_stderr())
            if commands:
                c = commands.pop(0)

                # Python 3 expects bytes string to transfer the data.
                if PY == 3:
                    c = c.decode()
                resp.write_stdin(c)
            else:
                break
        resp.close()
예제 #23
0
 def __init__(self, pod_config, input_file_names, output_file_name):
     if os.name == 'nt':
         msg = ('Local execution is provided for testing on Posix systems'
                'only. We detect you are using Windows.')
         logger.error(msg)
         raise NotImplementedError(msg)
     with open(pod_config, 'r') as fd:
         self.dep = yaml.load(fd, Loader=yaml.BaseLoader)
     self.input_file_names = input_file_names
     self.output_file_name = output_file_name
     config.load_kube_config()
     c = Configuration()
     c.assert_hostname = False
     Configuration.set_default(c)
     self.core_v1 = core_v1_api.CoreV1Api()
예제 #24
0
    def __init__(self, module, client):
        self.client = client
        self.module = module
        self.api_instance = core_v1_api.CoreV1Api(client.client)

        self.local_path = module.params.get("local_path")
        self.name = module.params.get("pod")
        self.namespace = module.params.get("namespace")
        self.remote_path = module.params.get("remote_path")
        self.content = module.params.get("content")

        self.no_preserve = module.params.get("no_preserve")
        self.container_arg = {}
        if module.params.get("container"):
            self.container_arg["container"] = module.params.get("container")
예제 #25
0
파일: k8s_cp.py 프로젝트: hhue13/ansible
    def __init__(self, module, client):
        self.client = client
        self.module = module
        self.api_instance = core_v1_api.CoreV1Api(client.client)

        self.local_path = module.params.get('local_path')
        self.name = module.params.get('pod')
        self.namespace = module.params.get('namespace')
        self.remote_path = module.params.get('remote_path')
        self.content = module.params.get('content')

        self.no_preserve = module.params.get('no_preserve')
        self.container_arg = {}
        if module.params.get('container'):
            self.container_arg['container'] = module.params.get('container')
예제 #26
0
    def watch(self, filter: constants.LogFilter):
        """获取实时日志"""
        core_v1 = core_v1_api.CoreV1Api(self.dynamic_client.client)

        w = watch.Watch()

        s = w.stream(
            core_v1.read_namespaced_pod_log,
            self.pod_name,
            self.namespace,
            tail_lines=filter.tail_lines,
            container=filter.container_name,
            timestamps=constants.LOG_SHOW_TIMESTAMPS,
            follow=True,
        )
        return s
예제 #27
0
    def test_watch_configmaps(self):
        client = api_client.ApiClient(configuration=self.config)
        api = core_v1_api.CoreV1Api(client)

        # create a configmap
        name_a = 'configmap-a-' + short_uuid()
        configmap_a = config_map_with_value(name_a, "a")
        api.create_namespaced_config_map(
            body=configmap_a, namespace='default')

        # list all configmaps and extract the resource version
        resp = api.list_namespaced_config_map('default', label_selector="e2e-tests=true")
        rv = resp.metadata.resource_version

        # create another configmap
        name_b = 'configmap-b-' + short_uuid()
        configmap_b = config_map_with_value(name_b, "b")
        api.create_namespaced_config_map(
            body=configmap_b, namespace='default')

        # patch configmap b
        configmap_b['data']['config'] = "{}"
        api.patch_namespaced_config_map(
            name=name_b, namespace='default', body=configmap_b)

        # delete all configmaps
        api.delete_collection_namespaced_config_map(
            namespace='default', label_selector="e2e-tests=true")

        w = watch.Watch()
        # expect to observe all events happened after the initial LIST
        expect = ['ADDED', 'MODIFIED', 'DELETED', 'DELETED']
        i = 0
        # start watching with the resource version we got from the LIST
        for event in w.stream(api.list_namespaced_config_map,
                              namespace='default',
                              resource_version=rv,
                              timeout_seconds=5,
                              label_selector="e2e-tests=true"):
            self.assertEqual(event['type'], expect[i])
            # Kubernetes doesn't guarantee the order of the two objects
            # being deleted
            if i < 2:
                self.assertEqual(event['object'].metadata.name, name_b)
            i = i + 1

        self.assertEqual(i, 4)
예제 #28
0
def delete_pod(data):
    api = core_v1_api.CoreV1Api()
    body = client.V1DeleteOptions()

    try:
        resp = api.delete_namespaced_pod(name=data["name"],
                                         namespace=data["namespace"],
                                         pretty="True",
                                         body=body,
                                         grace_period_seconds=5,
                                         propagation_policy='Foreground')
        return resp

    except Exception as e:
        if e.status != 404:
            log.exception("Unknown error:")
            return None
예제 #29
0
 def __init__(self, module):
     self.module = module
     self.k8s_ansible_mixin = K8sAnsibleMixin(module=self.module)
     self.k8s_ansible_mixin.client = get_api_client(module=self.module)
     self.k8s_ansible_mixin.module = self.module
     self.k8s_ansible_mixin.argspec = self.module.argument_spec
     self.k8s_ansible_mixin.check_mode = self.module.check_mode
     self.k8s_ansible_mixin.params = self.module.params
     self.k8s_ansible_mixin.fail_json = self.module.fail_json
     self.k8s_ansible_mixin.fail = self.module.fail_json
     self.k8s_ansible_mixin.exit_json = self.module.exit_json
     self.k8s_ansible_mixin.warn = self.module.warn
     self.k8s_ansible_mixin.warnings = []
     self.api_instance = core_v1_api.CoreV1Api(
         self.k8s_ansible_mixin.client.client)
     self.k8s_ansible_mixin.check_library_version()
     self.changed = False
예제 #30
0
    def test_exit_code(self):
        client = api_client.ApiClient(configuration=self.config)
        api = core_v1_api.CoreV1Api(client)

        name = 'busybox-test-' + short_uuid()
        pod_manifest = manifest_with_command(
            name, "while true;do date;sleep 5; done")
        resp = api.create_namespaced_pod(body=pod_manifest,
                                         namespace='default')
        self.assertEqual(name, resp.metadata.name)
        self.assertTrue(resp.status.phase)

        while True:
            resp = api.read_namespaced_pod(name=name,
                                           namespace='default')
            self.assertEqual(name, resp.metadata.name)
            self.assertTrue(resp.status.phase)
            if resp.status.phase == 'Running':
                break
            time.sleep(1)

        commands_expected_values = (
            (["false", 1]),
            (["/bin/sh", "-c", "sleep 1; exit 3"], 3),
            (["true", 0]),
            (["/bin/sh", "-c", "ls /"], 0)
        )
        for command, value in commands_expected_values:
            client = stream(
                api.connect_get_namespaced_pod_exec,
                name,
                'default',
                command=command,
                stderr=True,
                stdin=False,
                stdout=True,
                tty=False,
                _preload_content=False)

            self.assertIsNone(client.returncode)
            client.run_forever(timeout=10)
            self.assertEqual(client.returncode, value)

        resp = api.delete_namespaced_pod(name=name, body={},
                                         namespace='default')