Kaynağa Gözat

HUE-6080 [metadata] upgrade the API with sizing parameters

Romain Rigaux 8 yıl önce
ebeveyn
işleme
b950d2bb1d

+ 1 - 1
desktop/core/ext-py/navoptapi-0.1.0/PKG-INFO

@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: navoptapi
-Version: 0-untagged.2312.g2ef4bee.dirty
+Version: 0+untagged.3628.g9db772a.dirty
 Summary: Cloudera Navigator Optimizer Api
 Home-page: http://www.cloudera.com/
 Author: UNKNOWN

+ 13 - 1
desktop/core/ext-py/navoptapi-0.1.0/ccscli/__init__.py

@@ -17,7 +17,13 @@
 import os
 import re
 
-VERSION = "0.1.0"
+from ._version import get_versions
+
+
+__version__ = get_versions()['version']
+del get_versions
+
+VERSION = __version__
 
 CCSCLI_ROOT = os.path.dirname(os.path.abspath(__file__))
 
@@ -46,6 +52,12 @@ COMPLEX_TYPES = set([OBJECT_TYPE,
 DEFAULT_PROFILE_NAME = 'default'
 CCS_ACCESS_KEY_ID_KEY_NAME = 'ccs_access_key_id'
 CCS_PRIVATE_KEY_KEY_NAME = 'ccs_private_key'
+# Python argparse has a bug in which '-' are not parsed correctly if they appear
+# as values for other arguments, see: http://bugs.python.org/issue9334 for more
+# details. This defines special encoding for dash that we will "decode" and
+# replace with a dash. The reason we are using \\ is that there is a non zero
+# chance that customers can discover this themselves.
+ARGPARSE_DASH_ENCODING = '\\-'
 
 # Prepopulate the cache with special cases that don't match our regular
 # transformation.

+ 520 - 0
desktop/core/ext-py/navoptapi-0.1.0/ccscli/_version.py

@@ -0,0 +1,520 @@
+
+# This file helps to compute a version number in source trees obtained from
+# git-archive tarball (such as those provided by githubs download-from-tag
+# feature). Distribution tarballs (built by setup.py sdist) and build
+# directories (produced by setup.py build) will contain a much shorter file
+# that just contains the computed version number.
+
+# This file is released into the public domain. Generated by
+# versioneer-0.17 (https://github.com/warner/python-versioneer)
+
+"""Git implementation of _version.py."""
+
+import errno
+import os
+import re
+import subprocess
+import sys
+
+
+def get_keywords():
+    """Get the keywords needed to look up the version information."""
+    # these strings will be replaced by git during git-archive.
+    # setup.py/versioneer.py will grep for the variable names, so they must
+    # each be defined on a line of their own. _version.py will just call
+    # get_keywords().
+    git_refnames = "$Format:%d$"
+    git_full = "$Format:%H$"
+    git_date = "$Format:%ci$"
+    keywords = {"refnames": git_refnames, "full": git_full, "date": git_date}
+    return keywords
+
+
+class VersioneerConfig:
+    """Container for Versioneer configuration parameters."""
+
+
+def get_config():
+    """Create, populate and return the VersioneerConfig() object."""
+    # these strings are filled in when 'setup.py versioneer' creates
+    # _version.py
+    cfg = VersioneerConfig()
+    cfg.VCS = "git"
+    cfg.style = "pep440"
+    cfg.tag_prefix = "ccscli-"
+    cfg.parentdir_prefix = "None"
+    cfg.versionfile_source = "ccscli/_version.py"
+    cfg.verbose = False
+    return cfg
+
+
+class NotThisMethod(Exception):
+    """Exception raised if a method is not valid for the current scenario."""
+
+
+LONG_VERSION_PY = {}
+HANDLERS = {}
+
+
+def register_vcs_handler(vcs, method):  # decorator
+    """Decorator to mark a method as the handler for a particular VCS."""
+    def decorate(f):
+        """Store f in HANDLERS[vcs][method]."""
+        if vcs not in HANDLERS:
+            HANDLERS[vcs] = {}
+        HANDLERS[vcs][method] = f
+        return f
+    return decorate
+
+
+def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False,
+                env=None):
+    """Call the given command(s)."""
+    assert isinstance(commands, list)
+    p = None
+    for c in commands:
+        try:
+            dispcmd = str([c] + args)
+            # remember shell=False, so use git.cmd on windows, not just git
+            p = subprocess.Popen([c] + args, cwd=cwd, env=env,
+                                 stdout=subprocess.PIPE,
+                                 stderr=(subprocess.PIPE if hide_stderr
+                                         else None))
+            break
+        except EnvironmentError:
+            e = sys.exc_info()[1]
+            if e.errno == errno.ENOENT:
+                continue
+            if verbose:
+                print("unable to run %s" % dispcmd)
+                print(e)
+            return None, None
+    else:
+        if verbose:
+            print("unable to find command, tried %s" % (commands,))
+        return None, None
+    stdout = p.communicate()[0].strip()
+    if sys.version_info[0] >= 3:
+        stdout = stdout.decode()
+    if p.returncode != 0:
+        if verbose:
+            print("unable to run %s (error)" % dispcmd)
+            print("stdout was %s" % stdout)
+        return None, p.returncode
+    return stdout, p.returncode
+
+
+def versions_from_parentdir(parentdir_prefix, root, verbose):
+    """Try to determine the version from the parent directory name.
+
+    Source tarballs conventionally unpack into a directory that includes both
+    the project name and a version string. We will also support searching up
+    two directory levels for an appropriately named parent directory
+    """
+    rootdirs = []
+
+    for i in range(3):
+        dirname = os.path.basename(root)
+        if dirname.startswith(parentdir_prefix):
+            return {"version": dirname[len(parentdir_prefix):],
+                    "full-revisionid": None,
+                    "dirty": False, "error": None, "date": None}
+        else:
+            rootdirs.append(root)
+            root = os.path.dirname(root)  # up a level
+
+    if verbose:
+        print("Tried directories %s but none started with prefix %s" %
+              (str(rootdirs), parentdir_prefix))
+    raise NotThisMethod("rootdir doesn't start with parentdir_prefix")
+
+
+@register_vcs_handler("git", "get_keywords")
+def git_get_keywords(versionfile_abs):
+    """Extract version information from the given file."""
+    # the code embedded in _version.py can just fetch the value of these
+    # keywords. When used from setup.py, we don't want to import _version.py,
+    # so we do it with a regexp instead. This function is not used from
+    # _version.py.
+    keywords = {}
+    try:
+        f = open(versionfile_abs, "r")
+        for line in f.readlines():
+            if line.strip().startswith("git_refnames ="):
+                mo = re.search(r'=\s*"(.*)"', line)
+                if mo:
+                    keywords["refnames"] = mo.group(1)
+            if line.strip().startswith("git_full ="):
+                mo = re.search(r'=\s*"(.*)"', line)
+                if mo:
+                    keywords["full"] = mo.group(1)
+            if line.strip().startswith("git_date ="):
+                mo = re.search(r'=\s*"(.*)"', line)
+                if mo:
+                    keywords["date"] = mo.group(1)
+        f.close()
+    except EnvironmentError:
+        pass
+    return keywords
+
+
+@register_vcs_handler("git", "keywords")
+def git_versions_from_keywords(keywords, tag_prefix, verbose):
+    """Get version information from git keywords."""
+    if not keywords:
+        raise NotThisMethod("no keywords at all, weird")
+    date = keywords.get("date")
+    if date is not None:
+        # git-2.2.0 added "%cI", which expands to an ISO-8601 -compliant
+        # datestamp. However we prefer "%ci" (which expands to an "ISO-8601
+        # -like" string, which we must then edit to make compliant), because
+        # it's been around since git-1.5.3, and it's too difficult to
+        # discover which version we're using, or to work around using an
+        # older one.
+        date = date.strip().replace(" ", "T", 1).replace(" ", "", 1)
+    refnames = keywords["refnames"].strip()
+    if refnames.startswith("$Format"):
+        if verbose:
+            print("keywords are unexpanded, not using")
+        raise NotThisMethod("unexpanded keywords, not a git-archive tarball")
+    refs = set([r.strip() for r in refnames.strip("()").split(",")])
+    # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of
+    # just "foo-1.0". If we see a "tag: " prefix, prefer those.
+    TAG = "tag: "
+    tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)])
+    if not tags:
+        # Either we're using git < 1.8.3, or there really are no tags. We use
+        # a heuristic: assume all version tags have a digit. The old git %d
+        # expansion behaves like git log --decorate=short and strips out the
+        # refs/heads/ and refs/tags/ prefixes that would let us distinguish
+        # between branches and tags. By ignoring refnames without digits, we
+        # filter out many common branch names like "release" and
+        # "stabilization", as well as "HEAD" and "master".
+        tags = set([r for r in refs if re.search(r'\d', r)])
+        if verbose:
+            print("discarding '%s', no digits" % ",".join(refs - tags))
+    if verbose:
+        print("likely tags: %s" % ",".join(sorted(tags)))
+    for ref in sorted(tags):
+        # sorting will prefer e.g. "2.0" over "2.0rc1"
+        if ref.startswith(tag_prefix):
+            r = ref[len(tag_prefix):]
+            if verbose:
+                print("picking %s" % r)
+            return {"version": r,
+                    "full-revisionid": keywords["full"].strip(),
+                    "dirty": False, "error": None,
+                    "date": date}
+    # no suitable tags, so version is "0+unknown", but full hex is still there
+    if verbose:
+        print("no suitable tags, using unknown + full revision id")
+    return {"version": "0+unknown",
+            "full-revisionid": keywords["full"].strip(),
+            "dirty": False, "error": "no suitable tags", "date": None}
+
+
+@register_vcs_handler("git", "pieces_from_vcs")
+def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command):
+    """Get version from 'git describe' in the root of the source tree.
+
+    This only gets called if the git-archive 'subst' keywords were *not*
+    expanded, and _version.py hasn't already been rewritten with a short
+    version string, meaning we're inside a checked out source tree.
+    """
+    GITS = ["git"]
+    if sys.platform == "win32":
+        GITS = ["git.cmd", "git.exe"]
+
+    out, rc = run_command(GITS, ["rev-parse", "--git-dir"], cwd=root,
+                          hide_stderr=True)
+    if rc != 0:
+        if verbose:
+            print("Directory %s not under git control" % root)
+        raise NotThisMethod("'git rev-parse --git-dir' returned error")
+
+    # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty]
+    # if there isn't one, this yields HEX[-dirty] (no NUM)
+    describe_out, rc = run_command(GITS, ["describe", "--tags", "--dirty",
+                                          "--always", "--long",
+                                          "--match", "%s*" % tag_prefix],
+                                   cwd=root)
+    # --long was added in git-1.5.5
+    if describe_out is None:
+        raise NotThisMethod("'git describe' failed")
+    describe_out = describe_out.strip()
+    full_out, rc = run_command(GITS, ["rev-parse", "HEAD"], cwd=root)
+    if full_out is None:
+        raise NotThisMethod("'git rev-parse' failed")
+    full_out = full_out.strip()
+
+    pieces = {}
+    pieces["long"] = full_out
+    pieces["short"] = full_out[:7]  # maybe improved later
+    pieces["error"] = None
+
+    # parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty]
+    # TAG might have hyphens.
+    git_describe = describe_out
+
+    # look for -dirty suffix
+    dirty = git_describe.endswith("-dirty")
+    pieces["dirty"] = dirty
+    if dirty:
+        git_describe = git_describe[:git_describe.rindex("-dirty")]
+
+    # now we have TAG-NUM-gHEX or HEX
+
+    if "-" in git_describe:
+        # TAG-NUM-gHEX
+        mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe)
+        if not mo:
+            # unparseable. Maybe git-describe is misbehaving?
+            pieces["error"] = ("unable to parse git-describe output: '%s'"
+                               % describe_out)
+            return pieces
+
+        # tag
+        full_tag = mo.group(1)
+        if not full_tag.startswith(tag_prefix):
+            if verbose:
+                fmt = "tag '%s' doesn't start with prefix '%s'"
+                print(fmt % (full_tag, tag_prefix))
+            pieces["error"] = ("tag '%s' doesn't start with prefix '%s'"
+                               % (full_tag, tag_prefix))
+            return pieces
+        pieces["closest-tag"] = full_tag[len(tag_prefix):]
+
+        # distance: number of commits since tag
+        pieces["distance"] = int(mo.group(2))
+
+        # commit: short hex revision ID
+        pieces["short"] = mo.group(3)
+
+    else:
+        # HEX: no tags
+        pieces["closest-tag"] = None
+        count_out, rc = run_command(GITS, ["rev-list", "HEAD", "--count"],
+                                    cwd=root)
+        pieces["distance"] = int(count_out)  # total number of commits
+
+    # commit date: see ISO-8601 comment in git_versions_from_keywords()
+    date = run_command(GITS, ["show", "-s", "--format=%ci", "HEAD"],
+                       cwd=root)[0].strip()
+    pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1)
+
+    return pieces
+
+
+def plus_or_dot(pieces):
+    """Return a + if we don't already have one, else return a ."""
+    if "+" in pieces.get("closest-tag", ""):
+        return "."
+    return "+"
+
+
+def render_pep440(pieces):
+    """Build up version string, with post-release "local version identifier".
+
+    Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you
+    get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty
+
+    Exceptions:
+    1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty]
+    """
+    if pieces["closest-tag"]:
+        rendered = pieces["closest-tag"]
+        if pieces["distance"] or pieces["dirty"]:
+            rendered += plus_or_dot(pieces)
+            rendered += "%d.g%s" % (pieces["distance"], pieces["short"])
+            if pieces["dirty"]:
+                rendered += ".dirty"
+    else:
+        # exception #1
+        rendered = "0+untagged.%d.g%s" % (pieces["distance"],
+                                          pieces["short"])
+        if pieces["dirty"]:
+            rendered += ".dirty"
+    return rendered
+
+
+def render_pep440_pre(pieces):
+    """TAG[.post.devDISTANCE] -- No -dirty.
+
+    Exceptions:
+    1: no tags. 0.post.devDISTANCE
+    """
+    if pieces["closest-tag"]:
+        rendered = pieces["closest-tag"]
+        if pieces["distance"]:
+            rendered += ".post.dev%d" % pieces["distance"]
+    else:
+        # exception #1
+        rendered = "0.post.dev%d" % pieces["distance"]
+    return rendered
+
+
+def render_pep440_post(pieces):
+    """TAG[.postDISTANCE[.dev0]+gHEX] .
+
+    The ".dev0" means dirty. Note that .dev0 sorts backwards
+    (a dirty tree will appear "older" than the corresponding clean one),
+    but you shouldn't be releasing software with -dirty anyways.
+
+    Exceptions:
+    1: no tags. 0.postDISTANCE[.dev0]
+    """
+    if pieces["closest-tag"]:
+        rendered = pieces["closest-tag"]
+        if pieces["distance"] or pieces["dirty"]:
+            rendered += ".post%d" % pieces["distance"]
+            if pieces["dirty"]:
+                rendered += ".dev0"
+            rendered += plus_or_dot(pieces)
+            rendered += "g%s" % pieces["short"]
+    else:
+        # exception #1
+        rendered = "0.post%d" % pieces["distance"]
+        if pieces["dirty"]:
+            rendered += ".dev0"
+        rendered += "+g%s" % pieces["short"]
+    return rendered
+
+
+def render_pep440_old(pieces):
+    """TAG[.postDISTANCE[.dev0]] .
+
+    The ".dev0" means dirty.
+
+    Eexceptions:
+    1: no tags. 0.postDISTANCE[.dev0]
+    """
+    if pieces["closest-tag"]:
+        rendered = pieces["closest-tag"]
+        if pieces["distance"] or pieces["dirty"]:
+            rendered += ".post%d" % pieces["distance"]
+            if pieces["dirty"]:
+                rendered += ".dev0"
+    else:
+        # exception #1
+        rendered = "0.post%d" % pieces["distance"]
+        if pieces["dirty"]:
+            rendered += ".dev0"
+    return rendered
+
+
+def render_git_describe(pieces):
+    """TAG[-DISTANCE-gHEX][-dirty].
+
+    Like 'git describe --tags --dirty --always'.
+
+    Exceptions:
+    1: no tags. HEX[-dirty]  (note: no 'g' prefix)
+    """
+    if pieces["closest-tag"]:
+        rendered = pieces["closest-tag"]
+        if pieces["distance"]:
+            rendered += "-%d-g%s" % (pieces["distance"], pieces["short"])
+    else:
+        # exception #1
+        rendered = pieces["short"]
+    if pieces["dirty"]:
+        rendered += "-dirty"
+    return rendered
+
+
+def render_git_describe_long(pieces):
+    """TAG-DISTANCE-gHEX[-dirty].
+
+    Like 'git describe --tags --dirty --always -long'.
+    The distance/hash is unconditional.
+
+    Exceptions:
+    1: no tags. HEX[-dirty]  (note: no 'g' prefix)
+    """
+    if pieces["closest-tag"]:
+        rendered = pieces["closest-tag"]
+        rendered += "-%d-g%s" % (pieces["distance"], pieces["short"])
+    else:
+        # exception #1
+        rendered = pieces["short"]
+    if pieces["dirty"]:
+        rendered += "-dirty"
+    return rendered
+
+
+def render(pieces, style):
+    """Render the given version pieces into the requested style."""
+    if pieces["error"]:
+        return {"version": "unknown",
+                "full-revisionid": pieces.get("long"),
+                "dirty": None,
+                "error": pieces["error"],
+                "date": None}
+
+    if not style or style == "default":
+        style = "pep440"  # the default
+
+    if style == "pep440":
+        rendered = render_pep440(pieces)
+    elif style == "pep440-pre":
+        rendered = render_pep440_pre(pieces)
+    elif style == "pep440-post":
+        rendered = render_pep440_post(pieces)
+    elif style == "pep440-old":
+        rendered = render_pep440_old(pieces)
+    elif style == "git-describe":
+        rendered = render_git_describe(pieces)
+    elif style == "git-describe-long":
+        rendered = render_git_describe_long(pieces)
+    else:
+        raise ValueError("unknown style '%s'" % style)
+
+    return {"version": rendered, "full-revisionid": pieces["long"],
+            "dirty": pieces["dirty"], "error": None,
+            "date": pieces.get("date")}
+
+
+def get_versions():
+    """Get version information or return default if unable to do so."""
+    # I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have
+    # __file__, we can work backwards from there to the root. Some
+    # py2exe/bbfreeze/non-CPython implementations don't do __file__, in which
+    # case we can only use expanded keywords.
+
+    cfg = get_config()
+    verbose = cfg.verbose
+
+    try:
+        return git_versions_from_keywords(get_keywords(), cfg.tag_prefix,
+                                          verbose)
+    except NotThisMethod:
+        pass
+
+    try:
+        root = os.path.realpath(__file__)
+        # versionfile_source is the relative path from the top of the source
+        # tree (where the .git directory might live) to this file. Invert
+        # this to find the root from __file__.
+        for i in cfg.versionfile_source.split('/'):
+            root = os.path.dirname(root)
+    except NameError:
+        return {"version": "0+unknown", "full-revisionid": None,
+                "dirty": None,
+                "error": "unable to find root of source tree",
+                "date": None}
+
+    try:
+        pieces = git_pieces_from_vcs(cfg.tag_prefix, root, verbose)
+        return render(pieces, cfg.style)
+    except NotThisMethod:
+        pass
+
+    try:
+        if cfg.parentdir_prefix:
+            return versions_from_parentdir(cfg.parentdir_prefix, root, verbose)
+    except NotThisMethod:
+        pass
+
+    return {"version": "0+unknown", "full-revisionid": None,
+            "dirty": None,
+            "error": "unable to compute version", "date": None}

+ 23 - 17
desktop/core/ext-py/navoptapi-0.1.0/ccscli/auth.py

@@ -17,13 +17,12 @@ from base64 import urlsafe_b64encode
 from email.utils import formatdate
 import logging
 
+from asn1crypto import keys, pem
 from ccscli.compat import json
 from ccscli.compat import OrderedDict
 from ccscli.compat import urlsplit
 from ccscli.exceptions import NoCredentialsError
-from Crypto.Hash import SHA256
-from Crypto.PublicKey import RSA
-from Crypto.Signature import PKCS1_v1_5
+import rsa
 
 
 LOG = logging.getLogger('ccscli.auth')
@@ -43,10 +42,18 @@ class RSAv1Auth(BaseSigner):
     def __init__(self, credentials):
         self.credentials = credentials
 
-    def sign_string(self, string_to_sign):
+    def _sign_string(self, string_to_sign):
         try:
             # We expect the private key to be the an PKCS8 pem formatted string.
-            key = RSA.importKey(self.credentials.private_key)
+            pem_bytes = self.credentials.private_key.encode('utf-8')
+            if pem.detect(pem_bytes):
+                _, _, der_bytes = pem.unarmor(pem_bytes)
+                # In PKCS8 the key is wrapped in a container that describes it
+                info = keys.PrivateKeyInfo.load(der_bytes, strict=True)
+                # The unwrapped key is equivalent to pkcs1 contents
+                key = rsa.PrivateKey.load_pkcs1(info.unwrap().dump(), 'DER')
+            else:
+                raise Exception('Not a PEM file')
         except:
             message = \
                 "Failed to import private key from: '%s'. The private key is " \
@@ -60,11 +67,10 @@ class RSAv1Auth(BaseSigner):
             LOG.debug(message, exc_info=True)
             raise Exception(message)
         # We sign the hash.
-        h = SHA256.new(string_to_sign.encode('utf-8'))
-        signer = PKCS1_v1_5.new(key)
-        return urlsafe_b64encode(signer.sign(h)).strip().decode('utf-8')
+        signature = rsa.sign(string_to_sign.encode('utf-8'), key, 'SHA-256')
+        return urlsafe_b64encode(signature).strip().decode('utf-8')
 
-    def canonical_standard_headers(self, headers):
+    def _canonical_standard_headers(self, headers):
         interesting_headers = ['content-type', 'x-ccs-date']
         hoi = []
         if 'x-ccs-date' in headers:
@@ -81,17 +87,17 @@ class RSAv1Auth(BaseSigner):
                 hoi.append('')
         return '\n'.join(hoi)
 
-    def canonical_string(self, method, split, headers):
+    def _canonical_string(self, method, split, headers):
         cs = method.upper() + '\n'
-        cs += self.canonical_standard_headers(headers) + '\n'
+        cs += self._canonical_standard_headers(headers) + '\n'
         cs += split.path + '\n'
         cs += RSAv1Auth.AUTH_METHOD_NAME
         return cs
 
-    def get_signature(self, method, split, headers):
-        string_to_sign = self.canonical_string(method, split, headers)
+    def _get_signature(self, method, split, headers):
+        string_to_sign = self._canonical_string(method, split, headers)
         LOG.debug('StringToSign:\n%s', string_to_sign)
-        return self.sign_string(string_to_sign)
+        return self._sign_string(string_to_sign)
 
     def add_auth(self, request):
         if self.credentials is None:
@@ -99,9 +105,9 @@ class RSAv1Auth(BaseSigner):
         LOG.debug("Calculating signature using RSAv1Auth.")
         LOG.debug('HTTP request method: %s', request.method)
         split = urlsplit(request.url)
-        signature = self.get_signature(request.method,
-                                       split,
-                                       request.headers)
+        signature = self._get_signature(request.method,
+                                        split,
+                                        request.headers)
         self._inject_signature(request, signature)
 
     def _get_date(self):

+ 1 - 0
desktop/core/ext-py/navoptapi-0.1.0/ccscli/credentials.py

@@ -277,6 +277,7 @@ class SharedCredentialProvider(CredentialProvider):
         try:
             available_creds = raw_config_parse(self._creds_filename)
         except ConfigNotFound:
+            LOG.debug("Credentials file at %s does not exist!" % self._creds_filename)
             return None
         if self._profile_name in available_creds:
             config = available_creds[self._profile_name]

+ 72 - 0
desktop/core/ext-py/navoptapi-0.1.0/ccscli/exceptions.py

@@ -177,3 +177,75 @@ class ConfigParseError(CCSCLIError):
     The configuration file could not be parsed.
     """
     fmt = 'Unable to parse config file: {path}'
+
+
+class ClusterTerminatingError(CCSCLIError):
+
+    """
+    The cluster is terminating or has already terminated.
+    """
+    fmt = 'Cluster {cluster_name} is terminating.'
+
+
+class ClusterStartingError(CCSCLIError):
+
+    """
+    The cluster is starting.
+    """
+    fmt = 'Cluster {cluster_name} is starting.'
+
+
+class ClusterFailedError(CCSCLIError):
+
+    """
+    The cluster failed to start.
+    """
+    fmt = 'Cluster {cluster_name} failed to start.'
+
+
+class ClusterDoesNotExistError(CCSCLIError):
+
+    """
+    Cluster with the given name does not exist.
+    """
+    fmt = 'Cluster {cluster_name} does not exist.'
+
+
+class ClusterStatusNotFound(CCSCLIError):
+
+    """
+    Unable to find cluster status.
+    """
+    fmt = 'Unable to find {cluster_name}\'s status.'
+
+
+class ClusterEndpointNotFound(CCSCLIError):
+
+    """
+    Unable to find cluster's Cloudera Manager Endpoint.
+    """
+    fmt = 'Unable to find {cluster_name}\'s Cloudera Manager Endpoint.'
+
+
+class MultipleClustersExist(CCSCLIError):
+
+    """
+    Multiple clusters exist, expected single cluster.
+    """
+    fmt = 'Multiple clusters exist, expected single cluster.'
+
+
+class SSHNotFoundError(CCSCLIError):
+
+    """
+    SSH or Putty not available.
+    """
+    fmt = 'SSH or Putty not available.'
+
+
+class WrongPuttyKeyError(CCSCLIError):
+
+    """
+    A wrong key has been used with a compatible program.
+    """
+    fmt = 'Key file file format is incorrect. Putty expects a ppk file.'

+ 3 - 3
desktop/core/ext-py/navoptapi-0.1.0/navoptapi/_version.py

@@ -8,11 +8,11 @@ import json
 
 version_json = '''
 {
- "date": "2017-01-20T09:07:40-0800",
+ "date": "2017-03-15T10:41:50-0700",
  "dirty": true,
  "error": null,
- "full-revisionid": "2ef4beebbe2cfac713b2422ce1e2b71612a87b60",
- "version": "0+untagged.2312.g2ef4bee.dirty"
+ "full-revisionid": "9db772a3329363767a2ad503a538a2e02e7f0bdc",
+ "version": "0+untagged.3628.g9db772a.dirty"
 }
 '''  # END VERSION_JSON
 

+ 2 - 0
desktop/core/ext-py/navoptapi-0.1.0/setup.py

@@ -17,6 +17,8 @@ with open(path.join(here, 'README.rst'), encoding='utf-8') as f:
 requirements = ["python-dateutil>=2.1,<3.0.0",
                 "docutils>=0.10",
                 "pyyaml>=3.11",
+                "asn1crypto>=0.21.1",
+                "rsa>=3.4.2",
                 "colorama>=0.2.5,<=0.3.3",
                 "pycrypto>=2.6.1",
                 "requests>=2.9.1"]

+ 1 - 1
desktop/core/src/desktop/templates/hue.mako

@@ -218,7 +218,7 @@ ${ hueIcons.symbols() }
         % if 'jobbrowser' in apps:
         <!-- ko component: { name: 'hue-job-browser-panel', params: { onePageViewModel: onePageViewModel }} --><!-- /ko -->
         % endif
-        % endif
+
         % endif
       </div>
     </div>