def route(self, port=None, name=None, host=None): ports = self.xf_ports(self._data['ports']) if port is None and len(ports) == 1: port = ports[0] elif len(ports) == 0: raise UserError( ValueError("Can't create route on service with no ports!")) elif port is None: raise UserError(ValueError("Multiple ports available, pick one!")) elif Integer().do_check(port, None): for p in ports: if p._data['port'] == port or p._data['targetPort'] == port: port = p break elif String().do_check(port, None): for p in ports: if p._data['port'] == int( port) or p._data['targetPort'] == int(port): port = p break if p._data['name'] == port: port = p break if not isinstance(port, ServicePort): raise UserError( TypeError( "Unknown specification for port {}, please specify something consistent" .format(port))) return router.Route( port=router.RouteDestPort(targetPort=port._data['name']), to=[router.RouteDestService(name=self.name)], name=name, host=host)
def get_key(self, key): if self._data['type'] != 'Opaque': raise UserError(TypeError( "Can't create key object from non-'Opaque' (Secret) secret type (this is {})".format(self._data['type']))) if not key in self._data['secrets']: raise UserError(KeyError("Key {} doesn't exist in secret".format(key))) return SingleSecret(name=self._data['name'], namespace=self.namespace, key=key)
def check(self, value, path=None): if isinstance(value, VarEntity): ret = self.do_check(value.validation_value(), path=path) else: ret = self.do_check(value, path=path) if not ret and hasattr(self, 'validation_text'): raise UserError(KubeTypeValidationError(value, self.name(), path, self.validation_text)) elif not ret: raise UserError(KubeTypeValidationError(value, self.name(), path, 'Validation failed')) return ret
def do_validate(self): if self._data['operator'] in ('In', 'NotIn'): if self._data['values'] is None or len(self._data['values']) == 0: raise UserError( MatchExpressionInvalid( 'operator In/NotIn requires nonempty values')) else: if self._data['values'] is not None and len( self._data['values']) != 0: raise UserError( MatchExpressionInvalid( 'operator Exists/DoesNotExist requires empty values')) return True
def parse_obj(cls, doc): if cls is not KubeObj: raise ValueError(".parse_obj should only be called as KubeObj.parse_obj(...)") if not isinstance(doc, dict) or 'kind' not in doc or 'apiVersion' not in doc: raise UserError(ValueError( "Document needs to be a dictionary with 'kind' and 'apiVersion' as top-level keys")) my_cls = cls.find_class_from_obj(doc) if my_cls is not None: return my_cls().parser(doc) raise UserError(ValueError( "Unknown document kind: {}, no corresponding rubiks object found".format(doc['kind'])))
def to_string(self): if self._in_validation: return "command_output" env = {} if not self.env_clear: env.update(os.environ) if self.env is not None: for e in self.env: env[e] = str(self.env[e]) p = subprocess.Popen(map(str, self.cmd), close_fds=True, shell=False, cwd=self.cwd, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE) (out, err) = p.communicate() out = out.decode('utf8') err = err.decode('utf8') if len(err.strip()) != 0: print(err.rstrip(), file=sys.stderr) if self.rstrip: out = out.rstrip() if self.eol and out[-1] != '\n': out += '\n' if self.good_rc is None or rc in self.good_rc: return out raise UserError(CommandRuntimeException("Command {} ({}) exited with code rc={}".format( self.cmd[0], ' '.join(self.cmd), p.returncode)))
def clone(self, *args, **kwargs): ret = self._clone() ret._caller_file, ret._caller_line, ret._caller_fn = traceback.extract_stack( limit=2)[0][0:3] _rec_update_objs(self) if hasattr(self, 'identifier' ) and len(args) > 0 and self.identifier not in kwargs: kwargs[self.identifier] = args[0] for k in kwargs: if self.has_metadata and k in ('annotations', 'labels'): setattr(self, k, kwargs[k]) continue if k not in ret._data: raise UserError( TypeError( "{} is not a valid argument for {} constructor".format( k, ret.__class__.__name__))) if not isinstance(kwargs[k], (list, dict)): ret._data[k] = kwargs[k] elif isinstance(kwargs[k], list): ret._data[k] = [] ret._data[k].extend(kwargs[k]) else: if not isinstance(ret._data[k], dict): ret._data[k] = {} ret._data[k].update(kwargs[k]) return ret
def validate(self, path=None): if path is None: path = 'self' types = self.__class__.resolve_types() mapping = self.__class__._find_defaults('_map') if hasattr(self, 'labels'): Map(String, String).check(self.labels, '{}.(labels)'.format(path)) if hasattr(self, 'annotations'): Map(String, String).check(self.annotations, '{}.(annotations)'.format(path)) if not self.check_namespace(): raise UserError(KubeObjNoNamespace("No namespace attached to object at {}".format(path))) data = self.xform() for k in types: if k in data: types[k].check(data[k], path + '.' + k) else: types[k].check(None, path + '.' + k) for k in data: if k not in types and k not in mapping: raise KubeTypeUnresolvable( "Unknown data key {} - no type information".format(k)) sav_data = self._data try: self._data = data return self.do_validate() finally: self._data = sav_data
def __init__(self, collection, path): if path.basename == '' or path.basename.lower().strip( '0123456789abcdefghijklmnopqrstuvwxyz_') != '': raise UserError( ValueError( "Filenames should be python compliant (alphanumeric and '_'), found: {}" .format(path.basename))) if hasattr(self, 'extensions') and len(self.extensions) != 0: assert path.extension in self.extensions self.path = path self.collection = weakref.ref(collection) self.output_was_called = False self.default_import_args = {} self.import_exception = None if self.compile_in_init: save_cluster = KubeBaseObj._default_cluster try: KubeBaseObj._default_cluster = None self.module = self.do_compile() finally: KubeBaseObj._default_cluster = save_cluster
def run_command(*cmd, **kwargs): args = { 'cwd': None, 'env_clear': False, 'env': None, 'delay': True, 'ignore_rc': True, 'rstrip': True, 'eol': False } for k in kwargs: if k not in args: raise UserError( TypeError("{} isn't a valid argument to run_command()". format(k))) args.update(kwargs) cwd = None if args['cwd'] is not None: cwd = self.path.rel_path(args['cwd']) good_rc = None if not args['ignore_rc']: good_rc = (0, ) cmd_ent = kube_vartypes.Command(cmd, cwd=cwd, env_clear=args['env_clear'], env=args['env'], good_rc=good_rc, rstrip=args['rstrip'], eol=args['eol']) if args['delay']: return cmd_ent else: return str(cmd_ent)
def get_file_context(self, path): if path.extension is None: raise UserError( loader.LoaderFileNameError( "Filenames must have an extension in {}".format( path.full_path))) python_loader = self.__class__.get_python_file_type(path.extension) if python_loader is None: raise UserError( loader.LoaderFileNameError( "No valid handler for extension {} in {}".format( path.extension, path.full_path))) return self.get_or_add_file(path, python_loader, (self, path))
def get_ns(self, name): ret = _REG.get_id(Namespace, name) if ret is None: return Namespace(name) if len(ret) > 1: raise UserError( ValueError( "More than one namespace with name {} has been declared". format(name))) return ret[0]
def get_multi_python(self, py_context, pattern='*', basepath=None, **kwargs): extensions = self.__class__.get_python_file_type(None) ret = {} if pattern is None: raise UserError( ValueError("get_multi_python(): pattern must be specified")) basep = None if basepath is not None: try: basep = py_context.path.rel_path(basepath) except AssertionError as e: raise UserError( LoaderImportError( 'basepath specifiers in get_multi_python must be relative: {}' .format(basepath))) for p in self.find_all_source_files(): if basep is not None and os.path.relpath( p.repo_rel_path, basep.repo_rel_path).startswith('..'): continue if p.extension is None: continue if p.extension not in extensions: continue if not fnmatch.fnmatchcase(p.filename, pattern) and \ not fnmatch.fnmatchcase(p.basename, pattern): continue self.add_dep(self.current_context[-1], p) try: ret[p.repo_rel_path] = self.get_file_context(p).get_module( **kwargs) except loader.LoaderBaseException as e: handle_user_error(e) return ret
def validate(cls, surge, unavailable): def check_zero(v): if v is None: return True return (String().do_check(v, None) and int(v[:-1]) == 0) or (v == 0) if check_zero(surge) and check_zero(unavailable): raise UserError(SurgeError("maxSurge and maxUnavailable cannot both be zero")) return True
def __init__(self, *args, **kwargs): # put the identifier in if it's specified if hasattr(self, 'identifier' ) and len(args) > 0 and self.identifier not in kwargs: kwargs[self.identifier] = args[0] self._data = self.__class__._find_defaults('_defaults') self._caller_file, self._caller_line, self._caller_fn = traceback.extract_stack( limit=2)[0][0:3] for k in self.__class__._find_defaults('_map'): self._data[k] = None self.namespace = None self.set_namespace(KubeBaseObj._default_ns) self._in_cluster = KubeBaseObj._default_cluster if '_no_add' not in kwargs or not kwargs['_no_add']: if hasattr(self, 'add_obj'): self.add_obj() if '_no_add' in kwargs: del kwargs['_no_add'] if self.has_metadata: self.annotations = {} self.labels = {} if hasattr(self, 'early_init'): self.early_init(*args, **kwargs) for k in kwargs: if self.has_metadata and k in ('annotations', 'labels'): setattr(self, k, kwargs[k]) continue if k not in self._data: raise UserError( TypeError( "{} is not a valid argument for {} constructor".format( k, self.__class__.__name__))) if not isinstance(kwargs[k], (list, dict)): self._data[k] = kwargs[k] elif isinstance(kwargs[k], list): self._data[k] = [] self._data[k].extend(kwargs[k]) else: if not isinstance(self._data[k], dict): self._data[k] = {} self._data[k].update(kwargs[k]) _rec_update_objs(self)
def exec_saved(savedLines): saved_locals = get_starting_locals() try: exec(savedLines, saved_locals) except Exception: _, exc_obj, exc_tb = exc_info() raise UserError(exc_obj, exc_tb, saved_locals) # deepcopy cant handle imported modules, so remove them saved_locals = {k: v for k, v in saved_locals.items() if str(type(v)) != "<class 'module'>"} return saved_locals
def check(self, value, path=None): if not isinstance(value, dict): raise UserError(KubeTypeValidationError(value, self.name(), path, "not a dictionary")) if path is None: path = 'self' for k in value.keys(): self.key.check(k, path='{}[{}] (key)'.format(path, k)) self.value.check(value[k], path='{}[{}]'.format(path, k)) return True
def get_file_context(self, path): try: self.current_context.append(path) if path.extension is None: raise UserError( loader.LoaderFileNameError( "Filenames must have an extension in {}".format( path.full_path))) python_loader = self.__class__.get_python_file_type(path.extension) if python_loader is None: raise UserError( loader.LoaderFileNameError( "No valid handler for extension {} in {}".format( path.extension, path.full_path))) return self.get_or_add_file(path, python_loader, (self, path)) finally: assert self.current_context[-1] is path self.current_context.pop()
def import_python(self, py_context, name, exports, **kwargs): path = self.import_check(py_context, name) self.debug( 1, 'importing python {} ({} -> {})'.format( path.repo_rel_path, py_context.path.repo_rel_path, name)) basename = path.basename if 'import_as' in kwargs and kwargs['import_as'] is not None: basename = kwargs['import_as'] new_context = None try: new_context = self.get_file_context(path) if 'no_import' not in kwargs or not kwargs['no_import']: if 'no_import' in kwargs: del kwargs['no_import'] if 'import_as' in kwargs: del kwargs['import_as'] self.import_symbols(name, new_context.path, py_context.path, basename, new_context, py_context._current_module, exports, **kwargs) elif len(exports) != 0 or ('import_as' in kwargs and kwargs['import_as'] is not None): raise UserError( ValueError( "import_python: Can't set symbols to import to when using no_import" )) except loader.LoaderBaseException as e: raise UserError(e) self.add_dep(py_context.path, path) return new_context
def import_check(self, py_context, name, valid_exts=None): try: npath = py_context.path.rel_path(name) except AssertionError as e: raise UserError( LoaderImportError( 'path imports must be relative {} -> {}'.format( py_context.path.src_rel_path, name))) if valid_exts is not None: if npath.extension not in valid_exts: raise UserError( LoaderImportError( 'expected file extension in ({}), got .{}'.format( ', '.join(valid_exts), npath.extension))) if not npath.exists(): raise UserError( LoaderImportError( 'file {} -> {} imported from {} does not exist'.format( npath.src_rel_path, npath.full_path, py_context.path.src_rel_path))) return npath
def add_user(self, v): if isinstance(v, User) and v.name not in self._data['users']: self._data['users'].append(v.name) elif isinstance(v, ServiceAccount): sa_name = 'system:serviceaccount:' + v.namespace.name + ':' + v.name if sa_name not in self._data['users']: self._data['users'].append(sa_name) elif SystemIdentifier.do_check(v, None): self._data['users'].append(v) else: raise UserError(TypeError("can't add {} to users".format(repr(v))))
def get_ns(self, name): try: from kube_objs import Namespace ret = _REG.get_id(Namespace, name) if ret is None: return Namespace(name) if len(ret) > 1: raise UserError( ValueError( "More than one namespace with name {} has been declared". format(name))) return ret[0] except ImportError: return None
def get_branches(self, path): try: path = "" + path except: raise UserError( TypeError("Wrong type for path: expected str, got {}".format( path.__class__.__name__))) if len(path) == 0: raise UserError( ValueError( "path should not be empty string - use '.' for root")) if not self.has_data: return () if path == '.': return tuple(sorted(self.data.keys())) path_c = self._resolve_path(path).split('.') ctx = self.data i = 0 while i < len(path_c): if not isinstance(ctx, dict) or not path_c[i] in ctx: raise UserError( KeyNotExist("branch {} ({}) doesn't exist in {}".format( '.'.join(path_c[0:i]), path, self._get_repo_rel_path()))) ctx = ctx[path_c[i]] i += 1 if isinstance(ctx, dict): return tuple(sorted(ctx.keys())) return ()
def get_key(self, *args): e_txt = None for p in range(0, len(args)): last = False if p == len(args) - 1: last = True path = self._resolve_path(args[p]) try: if self.is_confidential: return Confidential(str(self._get_key(path, e_txt))) try: ret = self._get_key(path, e_txt) except InvalidKey as e: handle_user_error(e) if self.assert_type is not None and not isinstance( ret, self.assert_type): raise UserError( TypeError("return value of {} is not {}".format( path, self.assert_type))) return ret except Exception as e: e_txt = str(e) if last: if self.default is not None: if self.assert_type is not None and not isinstance( self.default, self.assert_type): raise UserError( TypeError( "return value of {} is not {}".format( path, self.assert_type))) return self.default handle_user_error(e)
def valid_clusters(*clusters): if len(clusters) == 0: raise UserError( ValueError( "Must specify at least one cluster")) all_clusters = tuple( self.collection().repository.get_clusters()) for cc in clusters: if cc not in all_clusters: print( "WARN: valid_clusters() called with unknown cluster name: " + cc, file=sys.stderr) if c not in clusters: raise PythonStopCompile("stop")
def check(self, value, path=None): if path is None: path = 'self' for t in self.types: try: if t.check(value, path): return True except UserError as e: if not isinstance(e.exc, KubeTypeValidationError): raise except KubeTypeValidationError: pass raise UserError(KubeTypeValidationError(value, self.name(), path, "couldn't match any possible types"))
def update(self, **kwargs): bad_args = set() for k in kwargs: if k in self._data: continue if self.has_metadata and k in ('labels', 'annotations'): continue bad_args.add(k) if len(bad_args) != 0: raise UserError(KeyError("{} isn't/aren't attributes of {}".format( ', '.join(map(lambda x: "'{}'".format(x), sorted(bad_args))), self.__class__.__name__))) for k in kwargs: if k in self._data: self._data[k] = kwargs[k] else: self.__setattr__(k, kwargs[k])
def check_for_dupes(self, op): ret = self._check_for_dupes(op) if ret is None: return new_obj = op.namespace_name + '/' + op.identifier orig_obj = new_obj if op.cluster is None: new_obj = "<all clusters>:" + new_obj else: new_obj = op.cluster + ":" + new_obj if ret[0] is None: orig_obj = "<all clusters>:" + orig_obj else: orig_obj = ret[0] + ":" + orig_obj raise UserError(RubiksOutputError("Duplicate (different) objects found: (orig) {}, (added) {}".format(orig_obj, new_obj)))
def copy_saved_imports_to_exec(codeToExec, savedLines): """ copies imports in savedLines to the top of codeToExec. If savedLines is empty this function does nothing. :raises: SyntaxError if err in savedLines """ if savedLines.strip() != "": try: saved_code_AST = ast.parse(savedLines) except SyntaxError: _, exc_obj, exc_tb = exc_info() raise UserError(exc_obj, exc_tb) imports = get_imports(saved_code_AST, savedLines) codeToExec = imports + "\n" + codeToExec # to make sure line # in errors is right we need to pad codeToExec with newlines numLinesToAdd = len(savedLines.split("\n")) - len(imports.split("\n")) for i in range(numLinesToAdd): codeToExec = "\n" + codeToExec return codeToExec
def _find_user(self, user_id): """ A function to return the class of the person. :param user_name: the user_name of the person calling the borrower. :return: a class of the person. """ # loops through all the users in self.user_list # and returns the class of the desired person. #TODO if there are two users with identical identifiers # the the last one will be returned - write in an exception # to give a proper error. # set a clicker that will show if the user has been found found_the_user = False for possible_user in self.available_users: # each user has an attribute that is a user id # and if it is the right one - return it if type(user_id) == int: if possible_user.user_id == user_id: ret_val = possible_user found_the_user = True if type(user_id) == str: if possible_user.name == user_id: ret_val = possible_user found_the_user = True if found_the_user: return ret_val else: raise UserError()