def get_available_addons(self, id=None, k8s_version=None):
        """Retrieve the available addons for a cluster.

        :param id: get available addons for a specific cluster (opt)
        :param k8s_version: get available addons for a cluster version (opt)
        """
        if id is not None and k8s_version is not None:
            print(
                "Either 'id' or 'k8s_version' parameter must be provided",
                file=sys.stderr,
            )
            sys.exit(1)

        if id is None and k8s_version is None:
            print(
                "Either 'id' or 'k8s_version' parameter must be provided",
                file=sys.stderr,
            )
            sys.exit(1)

        if id:
            print(base.get_client().k8s_cluster.get_available_addons(id=id))
        else:
            print(base.get_client().k8s_cluster.get_available_addons(
                k8s_version=k8s_version))
示例#2
0
    def set_storage(
        self,
        id,
        ephemeral_disks,
        persistent_disks=None,
    ):
        """Set storage for a k8s worker.

        Parameters
        ----------
        id : str
            The k8s worker ID
        ephemeral_disks : str
            Comma separated string containing ephemeral disks.
            e.g: "/dev/nvme2n1,/dev/nvme2n2"
        persistent_disks : str, optional
            Comma separated string containing persistent disks, by default
            None.
            e.g: "/dev/nvme1n1,/dev/nvme1n2"
        """
        if not ephemeral_disks:
            print("'ephemeral_disks' must be provided", file=sys.stderr)
            sys.exit(1)

        p_disks = (
            persistent_disks.split(",") if persistent_disks is not None else []
        )
        e_disks = ephemeral_disks.split(",")

        base.get_client().k8s_worker.set_storage(
            worker_id=id,
            persistent_disks=p_disks,
            ephemeral_disks=e_disks,
        )
示例#3
0
 def delete_all(self, ):
     """Delete all licenses."""
     response = base.get_client().license.list()
     all_license_keys = [
         str(unicode(li["LicenseKey"])) for li in response["Licenses"]
     ]
     for licence_key in all_license_keys:
         base.get_client().license.delete(license_key=licence_key)
示例#4
0
    def delete(
        self,
        license_key,
    ):
        """Delete a license by LicenseKey.

        :param license_key: The license key, e.g. '1234 1234 ... 1234
            "SOMETEXT"'
        """
        base.get_client().license.delete(license_key=license_key)
    def delete(
        self,
        url,
    ):
        """Make HTTP DELETE request.

        Examples
        --------
        $ hpecp httpclient delete /api/v1/workers/1
        """
        base.get_client()._request(
            url,
            http_method="delete",
            description="CLI HTTP DELETE",
        )
示例#6
0
    def list(
        self,
        output="yaml",
    ):
        """Get the system and user locks.

        :param output: how to display the output ['yaml'|'json']
        """
        if output not in ["yaml", "json"]:
            print(
                "'output' parameter must be 'yaml' or 'json'", file=sys.stderr
            )
            sys.exit(1)

        response = base.get_client().lock.get()

        if output == "yaml":
            print(
                yaml.dump(
                    yaml.load(
                        json.dumps(response),
                        Loader=yaml.FullLoader,
                    )
                )
            )
        else:
            print(json.dumps(response))
示例#7
0
    def list(
        self,
        output="yaml",
        license_key_only=False,
    ):
        """Retrieve the list of licenses.

        :param output: how to display the output ['yaml'|'json']
        """
        response = base.get_client().license.list()
        if license_key_only:
            response = [
                str(unicode(li["LicenseKey"])) for li in response["Licenses"]
            ]
            print("\n".join(response))
        else:
            if output == "yaml":
                print(
                    yaml.dump(
                        yaml.load(
                            json.dumps(response),
                            Loader=yaml.FullLoader,
                        )))
            else:
                print(json.dumps(response))
    def get(
        self,
        url,
    ):
        """Make HTTP GET request.

        Examples
        --------
        $ hpecp httpclient get /api/v1/workers
        > some output

        $ hpecp httpclient get /api/v2/tag | python3 -c \
            'import json,sys;obj=json.load(sys.stdin);[ print(t["_links"]["self"]["href"]) for t in obj["_embedded"]["tags"] if t["label"]["name"] == "Datafabric"]'
        /api/v2/tag/1
        """  # noqa:  E501
        response = base.get_client()._request(
            url,
            http_method="get",
            description="CLI HTTP GET",
        )

        try:
            response_info = json.dumps(response.json())
        except Exception:
            response_info = response.text

        print(response_info, file=sys.stdout)
示例#9
0
    def test_config_file_missing(self):
        def get_config_file():
            return "this_file_should_not_exist"

        with self.assertRaises(SystemExit) as cm:
            base.get_config_file = get_config_file
            base.get_client()

        self.assertEqual(cm.exception.code, 1)

        self.assertEqual(self.out.getvalue(), "")

        self.assertEqual(
            self.err.getvalue(),
            "Could not find configuration file 'this_file_should_not_exist'\n",
        )
    def import_cluster(
        self,
        cluster_type,
        name,
        description,
        pod_dns_domain,
        server_url,
        ca,
        bearer_token,
    ):
        """Import a k8s cluster.

        TODO

        Returns
        -------
        TODO

        Raises
        ------
        APIException
        """
        print(base.get_client().k8s_cluster.import_cluster(
            cluster_type,
            name,
            description,
            pod_dns_domain,
            server_url,
            ca,
            bearer_token,
        ))
 def k8smanifest(self):
     """Retrieve the k8smanifest."""
     response = base.get_client().k8s_cluster.k8smanifest()
     print(
         yaml.dump(yaml.load(
             json.dumps(response),
             Loader=yaml.FullLoader,
         )))
    def upgrade_cluster(self,
                        id,
                        k8s_upgrade_version,
                        worker_upgrade_percent=20):
        """Upgrade a cluster.

        TODO

        Returns
        -------
        TODO

        Raises
        ------
        APIException
        """
        base.get_client().k8s_cluster.upgrade_cluster(id, k8s_upgrade_version,
                                                      worker_upgrade_percent)
    def create_with_ssh_key(
        self,
        ip,
        proxy_node_hostname,
        ssh_key=None,
        ssh_key_file=None,
        ssh_passphrase=None,
        tags=[],
    ):
        """Create a Gateway using SSH key authentication.

        Parameters
        ----------
        ip : string
            The IP address of the proxy host.  Used for internal
            communication.
        proxy_node_hostname: string
            Clients will access cluster services will be accessed
            using this name.
        ssh_key: string
            The ssh key data as a string.  Alternatively, use the
            ssh_key_file parameter.
        ssh_key_file: string
            The file path to the ssh key.  Alternatively, use the
            ssh_key parameter.
        ssh_passphrase: string
            The passphrase
        tags: string
            Tags to add to the gateway, for example:
            "{ 'tag1': 'foo', 'tag2', 'bar' }".
        """
        if ssh_key is None and ssh_key_file is None:
            print(
                "Either ssh_key or ssh_key_file must be provided",
                file=sys.stderr,
            )
            sys.exit(1)

        if ssh_key is not None and ssh_key_file is not None:
            print(
                "Either ssh_key or ssh_key_file must be provided",
                file=sys.stderr,
            )
            sys.exit(1)

        if ssh_key_file:
            with open(ssh_key_file) as f:
                ssh_key = f.read()

        gateway_id = base.get_client().gateway.create_with_ssh_key(
            ip=ip,
            proxy_node_hostname=proxy_node_hostname,
            ssh_key_data=ssh_key,
            ssh_passphrase=ssh_passphrase,
            tags=tags,
        )
        print(gateway_id)
示例#14
0
 def delete_all(
     self,
     timeout_secs=300,
 ):
     """Delete all locks."""
     success = base.get_client().lock.delete_all(timeout_secs=timeout_secs)
     if not success:
         print("Could not delete locks.", file=sys.stderr)
         sys.exit(1)
    def admin_kube_config(self, id):
        """Retrieve a K8s Cluster Admin Kube Config.

        :param id: the cluster ID
        """
        print(base.get_client().k8s_cluster.get(id).admin_kube_config.replace(
            "\\n",
            "\n",
        ))
示例#16
0
    def create(
        self,
        name=None,
        description=None,
        tenant_type=None,
        k8s_cluster_id=None,
        is_namespace_owner=None,
        map_services_to_gateway=None,
        specified_namespace_name=None,
        adopt_existing_namespace=None,
        quota_memory=None,
        quota_persistent=None,
        quota_gpus=None,
        quota_cores=None,
        quota_disk=None,
        quota_tenant_storage=None,
        features=None,
    ):
        """Create a tenant.

        Parameters
        ----------
        name : [type], optional
            [description], by default None
        description : [type], optional
            [description], by default None
        tenant_type : [type], optional
            [description], by default None
        k8s_cluster_id : [type], optional
            [description], by default None
        is_namespace_owner : [type], optional
            [description], by default None
        map_services_to_gateway : [type], optional
            [description], by default None
        specified_namespace_name : [type], optional
            [description], by default None
        adopt_existing_namespace : [type], optional
            [description], by default None
        """
        tenant_id = base.get_client().tenant.create(
            name=name,
            description=description,
            tenant_type=tenant_type,
            k8s_cluster_id=k8s_cluster_id,
            is_namespace_owner=is_namespace_owner,
            map_services_to_gateway=map_services_to_gateway,
            specified_namespace_name=specified_namespace_name,
            adopt_existing_namespace=adopt_existing_namespace,
            quota_memory=quota_memory,
            quota_persistent=quota_persistent,
            quota_gpus=quota_gpus,
            quota_cores=quota_cores,
            quota_disk=quota_disk,
            quota_tenant_storage=quota_tenant_storage,
            features=features,
        )
        print(tenant_id)
示例#17
0
 def create(self, reason, timeout_secs=300):
     """Create a lock."""
     response = base.get_client().lock.create(reason, timeout_secs)
     if response is False:
         print(
             "Unable to lock within '{}'".format(timeout_secs),
             file=sys.stderr,
         )
     else:
         # reponse contains lock ID
         print(response, file=sys.stdout)
    def dashboard_url(
        self,
        id,
    ):
        """Retrieve a K8s Cluster Dashboard URL.

        :param id: the cluster ID
        """
        url = (base.get_client().k8s_cluster.get(
            id=id).dashboard_endpoint_access)
        print(url)
示例#19
0
    def register(
        self,
        server_filename,
    ):
        """Register a license.

        :param server_filename: Filepath to the license on the server, e.g.
            '/srv/bluedata/license/LICENSE-1.txt'
        """
        print(base.get_client().license.register(
            server_filename=server_filename))
    def dashboard_token(
        self,
        id,
    ):
        """Retrieve a K8s Cluster Dashboard Token.

        :param id: the cluster ID
        """
        token = base.get_client().k8s_cluster.get(id=id).dashboard_token
        if six.PY2:
            print(base64.b64decode(token.encode()))
        else:
            print(base64.b64decode(token.encode()).decode("utf-8"))
示例#21
0
    def k8skubeconfig(self):
        """Retrieve the tenant kubeconfig.

        This requires the ContainerPlatformClient to be created with
        a 'tenant' parameter.

        Returns
        -------
        str
            Tenant KubeConfig
        """
        conf = base.get_client().tenant.k8skubeconfig()
        print(conf)
示例#22
0
    def refresh(self, catalog_id):
        """Refresh a catalog.

        Parameters
        ----------
        catalog_id : str
            The ID of the catalog - format: '/api/v1/catalog/[0-9]+'

        Examples
        --------
        > hpecp catalog refresh /api/v1/catalog/99

        """
        try:
            base.get_client().catalog.refresh(catalog_id)

            # TODO: Report progress of the refresh workflow
        except AssertionError as ae:
            print(ae, file=sys.stderr)
            sys.exit(1)
        except (APIException, APIItemNotFoundException) as e:
            print(e.message, file=sys.stderr)
            sys.exit(1)
示例#23
0
    def install(self, catalog_id):
        """Install a catalog.

        Parameters
        ----------
        catalog_id : str
            The ID of the catalog - format: '/api/v1/catalog/[0-9]+'

        Examples
        --------
        > hpecp catalog install /api/v1/catalog/99

        """
        try:
            base.get_client().catalog.install(catalog_id)

            # TODO: Implement a way to check if the installation is actually
            # successful (and maybe report progress?) - wait_for_state()?
        except AssertionError as ae:
            print(ae, file=sys.stderr)
            sys.exit(1)
        except (APIException, APIItemNotFoundException) as e:
            print(e.message, file=sys.stderr)
            sys.exit(1)
示例#24
0
    def users(self, id, output="table", columns="ALL", query={}):
        """Retrieve users assigned to tenant.

        Parameters
        ----------
        id : str
            The tenant ID.
        """
        list_instance = base.get_client().tenant.users(id=id)
        self.print_list(
            list_instance=list_instance,
            output=output,
            columns=columns,
            query=query,
        )
    def add_addons(self, id, addons, wait_for_ready_sec=0):
        """Retrieve the installed addons on the cluster.

        :param id: get installed addons for a specific cluster
        :param addons: list of addons to install
        :param wait_for_ready_sec: wait for ready status
        (0 = do not wait)
        """
        if id is None:
            print("'id' parameter must be provided.", file=sys.stderr)
            sys.exit(1)
        if addons is None or not isinstance(addons, list) or len(addons) < 1:
            print(
                "'addons' must be a list with at least one entry.",
                file=sys.stderr,
            )
            sys.exit(1)

        base.get_client().k8s_cluster.add_addons(id=id, addons=addons)

        if wait_for_ready_sec > 0:
            self.wait_for_status(id=id,
                                 status=["ready"],
                                 timeout_secs=wait_for_ready_sec)
示例#26
0
    def get(
        self,
        url,
    ):
        """Make HTTP GET request.

        Examples
        --------
        $ hpecp httpclient get /api/v1/workers
        """
        response = base.get_client()._request(
            url,
            http_method="get",
            description="CLI HTTP GET",
        )
        print(response.text, file=sys.stdout)
示例#27
0
    def test_configure_cli_reads_hpecp_conf_user_provided_profile(self):

        # FIXME: why is this broken on 2.7?
        if six.PY2:
            return

        mock_data = dedent("""                [default]
                api_host = mock_host
                api_port = 9999
                use_ssl = True
                verify_ssl = False
                warn_ssl = True
                username = admin
                password = admin123

                [tenant1]
                api_host = tenant_mock_host
                username = tenant-admin
                password = tenant-password
                tenant = /api/v1/tenant/2""").encode("utf8")

        if six.PY2:
            builtins_name = "__builtin__.open"
        else:
            builtins_name = "builtins.open"

        with patch.dict("os.environ", {"PROFILE": "tenant1"}):
            with patch(builtins_name, mock_open(read_data=mock_data)):
                with patch("os.path.exists") as os_path_exists:

                    self.assertEqual(base.get_profile(), "tenant1")

                    # instruct the CLI that the mock file is actually
                    # ~/.hpecp.conf
                    os_path_exists.return_value = True

                    hpecp_client = base.get_client(start_session=False)

                    # this should be from the [default] section
                    self.assertEqual(hpecp_client.api_port, 9999)

                    # this should be from the [tenant1] section
                    self.assertEqual(hpecp_client.api_host, "tenant_mock_host")
                    self.assertEqual(hpecp_client.username, "tenant-admin")
                    self.assertEqual(hpecp_client.tenant_config,
                                     "/api/v1/tenant/2")
    def post(
        self,
        url,
        json_file="",
    ):
        """Make HTTP POST request.

        Examples
        --------
        $ cat > my.json <<-EOF
            {
                "external_identity_server":  {
                    "bind_pwd":"5ambaPwd@",
                    "user_attribute":"sAMAccountName",
                    "bind_type":"search_bind",
                    "bind_dn":"cn=Administrator,CN=Users,DC=samdom,DC=example,DC=com",
                    "host":"10.1.0.77",
                    "security_protocol":"ldaps",
                    "base_dn":"CN=Users,DC=samdom,DC=example,DC=com",
                    "verify_peer": false,
                    "type":"Active Directory",
                    "port":636
                }
            }
            EOF

            hpecp httpclient post /api/v2/config/auth --json-file my.json
        """
        with open(
            json_file,
            "r",
        ) as f:
            data = json.load(f)

        response = base.get_client()._request(
            url,
            http_method="post",
            data=data,
            description="CLI HTTP POST",
        )
        print(response.text, file=sys.stdout)
    def get(self, output="yaml", query=None):
        """Get the system config.

        :param output: how to display the output '[yaml|json|json-pp]'
        """
        if output not in ["yaml", "json", "json-pp", "text"]:
            print(
                ("'output' parameter must be 'yaml', 'json', "
                 "'json-pp' or 'text'."),
                file=sys.stderr,
            )
            sys.exit(1)

        if output == "yaml" and query is not None:
            print(
                "output=yaml is not supported with the query parameter.",
                file=sys.stderr,
            )
            sys.exit(1)

        response = base.get_client().install.get()

        if output == "yaml":
            print(
                yaml.dump(
                    yaml.load(
                        json.dumps(response),
                        Loader=yaml.FullLoader,
                    )))
        else:
            if query is None:
                data = response
            else:
                data = jmespath.search(str(query), response)

            if output == "json-pp":
                print(json.dumps(data, indent=4, sort_keys=True))
            elif output == "text":
                print(TextOutput.dump(data))
            else:
                print(json.dumps(data))
    def import_generic_cluster_with_json(self,
                                         json_file_path=None,
                                         json_content=None):
        """Import a generic cluster from json.

        TODO

        Returns
        -------
        TODO

        Raises
        ------
        APIException
        """
        assert (json_file_path is not None or json_content is not None
                ), "Either --json-file-path or --json-content must be provided"

        assert (
            json_file_path is None or json_content is None
        ), "Either --json-file-path or --json-content must be provided."

        if json_file_path:
            try:
                with open(json_file_path, "r") as f:
                    json_content = f.read()
            except OSError:
                print(
                    "Could not open/read json-file-path: {}".format(
                        json_file_path),
                    file=sys.stderr,
                )
                sys.exit(1)

        json_content = json.loads(json_content)

        print(base.get_client().k8s_cluster.import_generic_cluster_with_json(
            json_content))