Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
kube_config.py919 linesDownload Raw Back to config
1# Copyright 2018 The Kubernetes Authors.2#3# Licensed under the Apache License, Version 2.0 (the "License");4# you may not use this file except in compliance with the License.5# You may obtain a copy of the License at6#7#     http://www.apache.org/licenses/LICENSE-2.08#9# Unless required by applicable law or agreed to in writing, software10# distributed under the License is distributed on an "AS IS" BASIS,11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.12# See the License for the specific language governing permissions and13# limitations under the License.14 15import atexit16import base6417import copy18import datetime19import json20import logging21import os22import platform23import subprocess24import tempfile25import time26from collections import namedtuple27 28import oauthlib.oauth229import urllib330import yaml31from requests_oauthlib import OAuth2Session32from six import PY333 34from kubernetes.client import ApiClient, Configuration35from kubernetes.config.exec_provider import ExecProvider36 37from .config_exception import ConfigException38from .dateutil import UTC, format_rfc3339, parse_rfc333939 40try:41    import adal42except ImportError:43    pass44 45try:46    import google.auth47    import google.auth.transport.requests48    google_auth_available = True49except ImportError:50    google_auth_available = False51 52 53 54EXPIRY_SKEW_PREVENTION_DELAY = datetime.timedelta(minutes=5)55KUBE_CONFIG_DEFAULT_LOCATION = os.environ.get('KUBECONFIG', '~/.kube/config')56ENV_KUBECONFIG_PATH_SEPARATOR = ';' if platform.system() == 'Windows' else ':'57_temp_files = {}58 59 60def _cleanup_temp_files():61    global _temp_files62    for temp_file in _temp_files.values():63        try:64            os.remove(temp_file)65        except OSError:66            pass67    _temp_files = {}68 69 70def _create_temp_file_with_content(content, temp_file_path=None, force_recreate=False):71    if len(_temp_files) == 0:72        atexit.register(_cleanup_temp_files)73    # Because we may change context several times, try to remember files we74    # created and reuse them at a small memory cost.75    content_key = str(content)76    if not force_recreate and content_key in _temp_files:77        return _temp_files[content_key]78    if temp_file_path and not os.path.isdir(temp_file_path):79        os.makedirs(name=temp_file_path)80    fd, name = tempfile.mkstemp(dir=temp_file_path)81    os.close(fd)82    _temp_files[content_key] = name83    with open(name, 'wb') as fd:84        fd.write(content.encode() if isinstance(content, str) else content)85    return name86 87 88def _is_expired(expiry):89    return ((parse_rfc3339(expiry) - EXPIRY_SKEW_PREVENTION_DELAY) <=90            datetime.datetime.now(tz=UTC))91 92 93class FileOrData(object):94    """Utility class to read content of obj[%data_key_name] or file's95     content of obj[%file_key_name] and represent it as file or data.96     Note that the data is preferred. The obj[%file_key_name] will be used iff97     obj['%data_key_name'] is not set or empty. Assumption is file content is98     raw data and data field is base64 string. The assumption can be changed99     with base64_file_content flag. If set to False, the content of the file100     will assumed to be base64 and read as is. The default True value will101     result in base64 encode of the file content after read."""102 103    def __init__(self, obj, file_key_name, data_key_name=None,104                 file_base_path="", base64_file_content=True,105                 temp_file_path=None):106        if not data_key_name:107            data_key_name = file_key_name + "-data"108        self._file = None109        self._data = None110        self._base64_file_content = base64_file_content111        self._temp_file_path = temp_file_path112        if not obj:113            return114        if data_key_name in obj:115            self._data = obj[data_key_name]116        elif file_key_name in obj:117            self._file = os.path.normpath(118                os.path.join(file_base_path, obj[file_key_name]))119 120    def as_file(self):121        """If obj[%data_key_name] exists, return name of a file with base64122        decoded obj[%data_key_name] content otherwise obj[%file_key_name]."""123        use_data_if_no_file = not self._file and self._data124        if use_data_if_no_file:125            self._write_file()126 127            if self._file and not os.path.isfile(self._file):128                self._write_file(force_rewrite=True)129        if self._file and not os.path.isfile(self._file):130            raise ConfigException("File does not exist: %s" % self._file)131        return self._file132 133    def as_data(self):134        """If obj[%data_key_name] exists, Return obj[%data_key_name] otherwise135        base64 encoded string of obj[%file_key_name] file content."""136        use_file_if_no_data = not self._data and self._file137        if use_file_if_no_data:138            with open(self._file) as f:139                if self._base64_file_content:140                    self._data = bytes.decode(141                        base64.standard_b64encode(str.encode(f.read())))142                else:143                    self._data = f.read()144        return self._data145 146    def _write_file(self, force_rewrite=False):147        if self._base64_file_content:148            if isinstance(self._data, str):149                content = self._data.encode()150            else:151                content = self._data152            self._file = _create_temp_file_with_content(153                base64.standard_b64decode(content), self._temp_file_path, force_recreate=force_rewrite)154        else:155            self._file = _create_temp_file_with_content(156                self._data, self._temp_file_path, force_recreate=force_rewrite)157 158 159class CommandTokenSource(object):160    def __init__(self, cmd, args, tokenKey, expiryKey):161        self._cmd = cmd162        self._args = args163        if not tokenKey:164            self._tokenKey = '{.access_token}'165        else:166            self._tokenKey = tokenKey167        if not expiryKey:168            self._expiryKey = '{.token_expiry}'169        else:170            self._expiryKey = expiryKey171 172    def token(self):173        fullCmd = self._cmd + (" ") + " ".join(self._args)174        process = subprocess.Popen(175            [self._cmd] + self._args,176            stdout=subprocess.PIPE,177            stderr=subprocess.PIPE,178            universal_newlines=True)179        (stdout, stderr) = process.communicate()180        exit_code = process.wait()181        if exit_code != 0:182            msg = 'cmd-path: process returned %d' % exit_code183            msg += "\nCmd: %s" % fullCmd184            stderr = stderr.strip()185            if stderr:186                msg += '\nStderr: %s' % stderr187            raise ConfigException(msg)188        try:189            data = json.loads(stdout)190        except ValueError as de:191            raise ConfigException(192                'exec: failed to decode process output: %s' % de)193        A = namedtuple('A', ['token', 'expiry'])194        return A(195            token=data['credential']['access_token'],196            expiry=parse_rfc3339(data['credential']['token_expiry']))197 198 199class KubeConfigLoader(object):200 201    def __init__(self, config_dict, active_context=None,202                 get_google_credentials=None,203                 config_base_path="",204                 config_persister=None,205                 temp_file_path=None):206 207        if config_dict is None:208            raise ConfigException(209                'Invalid kube-config. '210                'Expected config_dict to not be None.')211        elif isinstance(config_dict, ConfigNode):212            self._config = config_dict213        else:214            self._config = ConfigNode('kube-config', config_dict)215 216        self._current_context = None217        self._user = None218        self._cluster = None219        self.set_active_context(active_context)220        self._config_base_path = config_base_path221        self._config_persister = config_persister222        self._temp_file_path = temp_file_path223 224        def _refresh_credentials_with_cmd_path():225            config = self._user['auth-provider']['config']226            cmd = config['cmd-path']227            if len(cmd) == 0:228                raise ConfigException(229                    'missing access token cmd '230                    '(cmd-path is an empty string in your kubeconfig file)')231            if 'scopes' in config and config['scopes'] != "":232                raise ConfigException(233                    'scopes can only be used '234                    'when kubectl is using a gcp service account key')235            args = []236            if 'cmd-args' in config:237                args = config['cmd-args'].split()238            else:239                fields = config['cmd-path'].split()240                cmd = fields[0]241                args = fields[1:]242 243            commandTokenSource = CommandTokenSource(244                cmd, args,245                config.safe_get('token-key'),246                config.safe_get('expiry-key'))247            return commandTokenSource.token()248 249        def _refresh_credentials():250            # Refresh credentials using cmd-path251            if ('auth-provider' in self._user and252                'config' in self._user['auth-provider'] and253                    'cmd-path' in self._user['auth-provider']['config']):254                return _refresh_credentials_with_cmd_path()255            256            # Make the Google auth block optional.257            if google_auth_available:258                credentials, project_id = google.auth.default(scopes=[259                    'https://www.googleapis.com/auth/cloud-platform',260                    'https://www.googleapis.com/auth/userinfo.email'261                ])262                request = google.auth.transport.requests.Request()263                credentials.refresh(request)264                return credentials265            else:266                return None267            268        if get_google_credentials:269            self._get_google_credentials = get_google_credentials270        else:271            self._get_google_credentials = _refresh_credentials272 273    def set_active_context(self, context_name=None):274        if context_name is None:275            context_name = self._config['current-context']276        self._current_context = self._config['contexts'].get_with_name(277            context_name)278        if (self._current_context['context'].safe_get('user') and279                self._config.safe_get('users')):280            user = self._config['users'].get_with_name(281                self._current_context['context']['user'], safe=True)282            if user:283                self._user = user['user']284            else:285                self._user = None286        else:287            self._user = None288        self._cluster = self._config['clusters'].get_with_name(289            self._current_context['context']['cluster'])['cluster']290 291    def _load_authentication(self):292        """Read authentication from kube-config user section if exists.293 294        This function goes through various authentication methods in user295        section of kube-config and stops if it finds a valid authentication296        method. The order of authentication methods is:297 298            1. auth-provider (gcp, azure, oidc)299            2. token field (point to a token file)300            3. exec provided plugin301            4. username/password302        """303        if not self._user:304            return305        if self._load_auth_provider_token():306            return307        if self._load_user_token():308            return309        if self._load_from_exec_plugin():310            return311        self._load_user_pass_token()312 313    def _load_auth_provider_token(self):314        if 'auth-provider' not in self._user:315            return316        provider = self._user['auth-provider']317        if 'name' not in provider:318            return319        if provider['name'] == 'gcp':320            return self._load_gcp_token(provider)321        if provider['name'] == 'azure':322            return self._load_azure_token(provider)323        if provider['name'] == 'oidc':324            return self._load_oid_token(provider)325 326    def _azure_is_expired(self, provider):327        expires_on = provider['config']['expires-on']328        if expires_on.isdigit():329            return int(expires_on) < time.time()330        else:331            exp_time = time.strptime(expires_on, '%Y-%m-%d %H:%M:%S.%f')332            return exp_time < time.gmtime()333 334    def _load_azure_token(self, provider):335        if 'config' not in provider:336            return337        if 'access-token' not in provider['config']:338            return339        if 'expires-on' in provider['config']:340            if self._azure_is_expired(provider):341                self._refresh_azure_token(provider['config'])342        self.token = 'Bearer %s' % provider['config']['access-token']343        return self.token344 345    def _refresh_azure_token(self, config):346        if 'adal' not in globals():347            raise ImportError('refresh token error, adal library not imported')348 349        tenant = config['tenant-id']350        authority = 'https://login.microsoftonline.com/{}'.format(tenant)351        context = adal.AuthenticationContext(352            authority, validate_authority=True, api_version='1.0'353        )354        refresh_token = config['refresh-token']355        client_id = config['client-id']356        apiserver_id = '00000002-0000-0000-c000-000000000000'357        try:358            apiserver_id = config['apiserver-id']359        except ConfigException:360            # We've already set a default above361            pass362        token_response = context.acquire_token_with_refresh_token(363            refresh_token, client_id, apiserver_id)364 365        provider = self._user['auth-provider']['config']366        provider.value['access-token'] = token_response['accessToken']367        provider.value['expires-on'] = token_response['expiresOn']368        if self._config_persister:369            self._config_persister()370 371    def _load_gcp_token(self, provider):372        if (('config' not in provider) or373                ('access-token' not in provider['config']) or374                ('expiry' in provider['config'] and375                 _is_expired(provider['config']['expiry']))):376            # token is not available or expired, refresh it377            self._refresh_gcp_token()378 379        self.token = "Bearer %s" % provider['config']['access-token']380        if 'expiry' in provider['config']:381            self.expiry = parse_rfc3339(provider['config']['expiry'])382        return self.token383 384    def _refresh_gcp_token(self):385        if 'config' not in self._user['auth-provider']:386            self._user['auth-provider'].value['config'] = {}387        provider = self._user['auth-provider']['config']388        credentials = self._get_google_credentials()389        provider.value['access-token'] = credentials.token390        provider.value['expiry'] = format_rfc3339(credentials.expiry)391        if self._config_persister:392            self._config_persister()393 394    def _load_oid_token(self, provider):395        if 'config' not in provider:396            return397 398        reserved_characters = frozenset(["=", "+", "/"])399        token = provider['config']['id-token']400 401        if any(char in token for char in reserved_characters):402            # Invalid jwt, as it contains url-unsafe chars403            return404 405        parts = token.split('.')406        if len(parts) != 3:  # Not a valid JWT407            return408 409        padding = (4 - len(parts[1]) % 4) * '='410        if len(padding) == 3:411            # According to spec, 3 padding characters cannot occur412            # in a valid jwt413            # https://tools.ietf.org/html/rfc7515#appendix-C414            return415 416        if PY3:417            jwt_attributes = json.loads(418                base64.urlsafe_b64decode(parts[1] + padding).decode('utf-8')419            )420        else:421            jwt_attributes = json.loads(422                base64.b64decode(parts[1] + padding)423            )424 425        expire = jwt_attributes.get('exp')426 427        if ((expire is not None) and428            (_is_expired(datetime.datetime.fromtimestamp(expire,429                                                         tz=UTC)))):430            self._refresh_oidc(provider)431 432            if self._config_persister:433                self._config_persister()434 435        self.token = "Bearer %s" % provider['config']['id-token']436 437        return self.token438 439    def _refresh_oidc(self, provider):440        config = Configuration()441 442        if 'idp-certificate-authority-data' in provider['config']:443            ca_cert = tempfile.NamedTemporaryFile(delete=True)444 445            if PY3:446                cert = base64.b64decode(447                    provider['config']['idp-certificate-authority-data']448                ).decode('utf-8')449            else:450                cert = base64.b64decode(451                    provider['config']['idp-certificate-authority-data'] + "=="452                )453 454            with open(ca_cert.name, 'w') as fh:455                fh.write(cert)456 457            config.ssl_ca_cert = ca_cert.name458 459        elif 'idp-certificate-authority' in provider['config']:460            config.ssl_ca_cert = provider['config']['idp-certificate-authority']461 462        else:463            config.verify_ssl = False464 465        client = ApiClient(configuration=config)466 467        response = client.request(468            method="GET",469            url="%s/.well-known/openid-configuration"470            % provider['config']['idp-issuer-url']471        )472 473        if response.status != 200:474            return475 476        response = json.loads(response.data)477 478        request = OAuth2Session(479            client_id=provider['config']['client-id'],480            token=provider['config']['refresh-token'],481            auto_refresh_kwargs={482                'client_id': provider['config']['client-id'],483                'client_secret': provider['config']['client-secret']484            },485            auto_refresh_url=response['token_endpoint']486        )487 488        try:489            refresh = request.refresh_token(490                token_url=response['token_endpoint'],491                refresh_token=provider['config']['refresh-token'],492                auth=(provider['config']['client-id'],493                      provider['config']['client-secret']),494                verify=config.ssl_ca_cert if config.verify_ssl else None495            )496        except oauthlib.oauth2.rfc6749.errors.InvalidClientIdError:497            return498 499        provider['config'].value['id-token'] = refresh['id_token']500        provider['config'].value['refresh-token'] = refresh['refresh_token']501 502    def _load_from_exec_plugin(self):503        if 'exec' not in self._user:504            return505        try:506            base_path = self._get_base_path(self._cluster.path)507            status = ExecProvider(self._user['exec'], base_path, self._cluster).run()508            if 'token' in status:509                self.token = "Bearer %s" % status['token']510            elif 'clientCertificateData' in status:511                # https://kubernetes.io/docs/reference/access-authn-authz/authentication/#input-and-output-formats512                # Plugin has provided certificates instead of a token.513                if 'clientKeyData' not in status:514                    logging.error('exec: missing clientKeyData field in '515                                  'plugin output')516                    return None517                self.cert_file = FileOrData(518                    status, None,519                    data_key_name='clientCertificateData',520                    file_base_path=base_path,521                    base64_file_content=False,522                    temp_file_path=self._temp_file_path).as_file()523                self.key_file = FileOrData(524                    status, None,525                    data_key_name='clientKeyData',526                    file_base_path=base_path,527                    base64_file_content=False,528                    temp_file_path=self._temp_file_path).as_file()529            else:530                logging.error('exec: missing token or clientCertificateData '531                              'field in plugin output')532                return None533            if 'expirationTimestamp' in status:534                self.expiry = parse_rfc3339(status['expirationTimestamp'])535            return True536        except Exception as e:537            logging.error(str(e))538 539    def _load_user_token(self):540        base_path = self._get_base_path(self._user.path)541        token = FileOrData(542            self._user, 'tokenFile', 'token',543            file_base_path=base_path,544            base64_file_content=False,545            temp_file_path=self._temp_file_path).as_data()546        if token:547            self.token = "Bearer %s" % token548            return True549 550    def _load_user_pass_token(self):551        if 'username' in self._user and 'password' in self._user:552            self.token = urllib3.util.make_headers(553                basic_auth=(self._user['username'] + ':' +554                            self._user['password'])).get('authorization')555            return True556 557    def _get_base_path(self, config_path):558        if self._config_base_path is not None:559            return self._config_base_path560        if config_path is not None:561            return os.path.abspath(os.path.dirname(config_path))562        return ""563 564    def _load_cluster_info(self):565        if 'server' in self._cluster:566            self.host = self._cluster['server'].rstrip('/')567            if self.host.startswith("https"):568                base_path = self._get_base_path(self._cluster.path)569                self.ssl_ca_cert = FileOrData(570                    self._cluster, 'certificate-authority',571                    file_base_path=base_path,572                    temp_file_path=self._temp_file_path).as_file()573                if 'cert_file' not in self.__dict__:574                    # cert_file could have been provided by575                    # _load_from_exec_plugin; only load from the _user576                    # section if we need it.577                    self.cert_file = FileOrData(578                        self._user, 'client-certificate',579                        file_base_path=base_path,580                        temp_file_path=self._temp_file_path).as_file()581                    self.key_file = FileOrData(582                        self._user, 'client-key',583                        file_base_path=base_path,584                        temp_file_path=self._temp_file_path).as_file()585        if 'insecure-skip-tls-verify' in self._cluster:586            self.verify_ssl = not self._cluster['insecure-skip-tls-verify']587        if 'tls-server-name' in self._cluster:588            self.tls_server_name = self._cluster['tls-server-name']589 590    def _set_config(self, client_configuration):591        if 'token' in self.__dict__:592            client_configuration.api_key['authorization'] = self.token593 594            def _refresh_api_key(client_configuration):595                if ('expiry' in self.__dict__ and _is_expired(self.expiry)):596                    self._load_authentication()597                self._set_config(client_configuration)598            client_configuration.refresh_api_key_hook = _refresh_api_key599        # copy these keys directly from self to configuration object600        keys = ['host', 'ssl_ca_cert', 'cert_file', 'key_file', 'verify_ssl','tls_server_name']601        for key in keys:602            if key in self.__dict__:603                setattr(client_configuration, key, getattr(self, key))604 605    def load_and_set(self, client_configuration):606        self._load_authentication()607        self._load_cluster_info()608        self._set_config(client_configuration)609 610    def list_contexts(self):611        return [context.value for context in self._config['contexts']]612 613    @property614    def current_context(self):615        return self._current_context.value616 617 618class ConfigNode(object):619    """Remembers each config key's path and construct a relevant exception620    message in case of missing keys. The assumption is all access keys are621    present in a well-formed kube-config."""622 623    def __init__(self, name, value, path=None):624        self.name = name625        self.value = value626        self.path = path627 628    def __contains__(self, key):629        return key in self.value630 631    def __len__(self):632        return len(self.value)633 634    def safe_get(self, key):635        if (isinstance(self.value, list) and isinstance(key, int) or636                key in self.value):637            return self.value[key]638 639    def __getitem__(self, key):640        v = self.safe_get(key)641        if v is None:642            raise ConfigException(643                'Invalid kube-config file. Expected key %s in %s'644                % (key, self.name))645        if isinstance(v, dict) or isinstance(v, list):646            return ConfigNode('%s/%s' % (self.name, key), v, self.path)647        else:648            return v649 650    def get_with_name(self, name, safe=False):651        if not isinstance(self.value, list):652            raise ConfigException(653                'Invalid kube-config file. Expected %s to be a list'654                % self.name)655        result = None656        for v in self.value:657            if 'name' not in v:658                raise ConfigException(659                    'Invalid kube-config file. '660                    'Expected all values in %s list to have \'name\' key'661                    % self.name)662            if v['name'] == name:663                if result is None:664                    result = v665                else:666                    raise ConfigException(667                        'Invalid kube-config file. '668                        'Expected only one object with name %s in %s list'669                        % (name, self.name))670        if result is not None:671            if isinstance(result, ConfigNode):672                return result673            else:674                return ConfigNode(675                    '%s[name=%s]' %676                    (self.name, name), result, self.path)677        if safe:678            return None679        raise ConfigException(680            'Invalid kube-config file. '681            'Expected object with name %s in %s list' % (name, self.name))682 683 684class KubeConfigMerger:685 686    """Reads and merges configuration from one or more kube-config's.687    The property `config` can be passed to the KubeConfigLoader as config_dict.688 689    It uses a path attribute from ConfigNode to store the path to kubeconfig.690    This path is required to load certs from relative paths.691 692    A method `save_changes` updates changed kubeconfig's (it compares current693    state of dicts with).694    """695 696    def __init__(self, paths):697        self.paths = []698        self.config_files = {}699        self.config_merged = None700        if hasattr(paths, 'read'):701            self._load_config_from_file_like_object(paths)702        else:703            self._load_config_from_file_path(paths)704 705    @property706    def config(self):707        return self.config_merged708 709    def _load_config_from_file_like_object(self, string):710        if hasattr(string, 'getvalue'):711            config = yaml.safe_load(string.getvalue())712        else:713            config = yaml.safe_load(string.read())714 715        if config is None:716            raise ConfigException(717                'Invalid kube-config.')718        if self.config_merged is None:719            self.config_merged = copy.deepcopy(config)720        # doesn't need to do any further merging721 722    def _load_config_from_file_path(self, string):723        for path in string.split(ENV_KUBECONFIG_PATH_SEPARATOR):724            if path:725                path = os.path.expanduser(path)726                if os.path.exists(path):727                    self.paths.append(path)728                    self.load_config(path)729        self.config_saved = copy.deepcopy(self.config_files)730 731    def load_config(self, path):732        with open(path) as f:733            config = yaml.safe_load(f)734 735        if config is None:736            raise ConfigException(737                'Invalid kube-config. '738                '%s file is empty' % path)739 740        if self.config_merged is None:741            config_merged = copy.deepcopy(config)742            for item in ('clusters', 'contexts', 'users'):743                config_merged[item] = []744            self.config_merged = ConfigNode(path, config_merged, path)745        for item in ('clusters', 'contexts', 'users'):746            self._merge(item, config.get(item, []) or [], path)747 748        if 'current-context' in config:749            self.config_merged.value['current-context'] = config['current-context']750 751        self.config_files[path] = config752 753    def _merge(self, item, add_cfg, path):754        for new_item in add_cfg:755            for exists in self.config_merged.value[item]:756                if exists['name'] == new_item['name']:757                    break758            else:759                self.config_merged.value[item].append(ConfigNode(760                    '{}/{}'.format(path, new_item), new_item, path))761 762    def save_changes(self):763        for path in self.paths:764            if self.config_saved[path] != self.config_files[path]:765                self.save_config(path)766        self.config_saved = copy.deepcopy(self.config_files)767 768    def save_config(self, path):769        with open(path, 'w') as f:770            yaml.safe_dump(self.config_files[path], f,771                           default_flow_style=False)772 773 774def _get_kube_config_loader_for_yaml_file(775        filename, persist_config=False, **kwargs):776    return _get_kube_config_loader(777        filename=filename,778        persist_config=persist_config,779        **kwargs)780 781 782def _get_kube_config_loader(783        filename=None,784        config_dict=None,785        persist_config=False,786        **kwargs):787    if config_dict is None:788        kcfg = KubeConfigMerger(filename)789        if persist_config and 'config_persister' not in kwargs:790            kwargs['config_persister'] = kcfg.save_changes791 792        if kcfg.config is None:793            raise ConfigException(794                'Invalid kube-config file. '795                'No configuration found.')796        return KubeConfigLoader(797            config_dict=kcfg.config,798            config_base_path=None,799            **kwargs)800    else:801        return KubeConfigLoader(802            config_dict=config_dict,803            config_base_path=None,804            **kwargs)805 806 807def list_kube_config_contexts(config_file=None):808 809    if config_file is None:810        config_file = KUBE_CONFIG_DEFAULT_LOCATION811 812    loader = _get_kube_config_loader(filename=config_file)813    return loader.list_contexts(), loader.current_context814 815 816def load_kube_config(config_file=None, context=None,817                     client_configuration=None,818                     persist_config=True,819                     temp_file_path=None):820    """Loads authentication and cluster information from kube-config file821    and stores them in kubernetes.client.configuration.822 823    :param config_file: Name of the kube-config file.824    :param context: set the active context. If is set to None, current_context825        from config file will be used.826    :param client_configuration: The kubernetes.client.Configuration to827        set configs to.828    :param persist_config: If True, config file will be updated when changed829        (e.g GCP token refresh).830    :param temp_file_path: store temp files path.831    """832 833    if config_file is None:834        config_file = KUBE_CONFIG_DEFAULT_LOCATION835 836    loader = _get_kube_config_loader(837        filename=config_file, active_context=context,838        persist_config=persist_config,839        temp_file_path=temp_file_path)840 841    if client_configuration is None:842        config = type.__call__(Configuration)843        loader.load_and_set(config)844        Configuration.set_default(config)845    else:846        loader.load_and_set(client_configuration)847 848 849def load_kube_config_from_dict(config_dict, context=None,850                               client_configuration=None,851                               persist_config=True,852                               temp_file_path=None):853    """Loads authentication and cluster information from config_dict file854    and stores them in kubernetes.client.configuration.855 856    :param config_dict: Takes the config file as a dict.857    :param context: set the active context. If is set to None, current_context858        from config file will be used.859    :param client_configuration: The kubernetes.client.Configuration to860        set configs to.861    :param persist_config: If True, config file will be updated when changed862        (e.g GCP token refresh).863    :param temp_file_path: store temp files path.864    """865    if config_dict is None:866        raise ConfigException(867            'Invalid kube-config dict. '868            'No configuration found.')869 870    loader = _get_kube_config_loader(871        config_dict=config_dict, active_context=context,872        persist_config=persist_config,873        temp_file_path=temp_file_path)874 875    if client_configuration is None:876        config = type.__call__(Configuration)877        loader.load_and_set(config)878        Configuration.set_default(config)879    else:880        loader.load_and_set(client_configuration)881 882 883def new_client_from_config(884        config_file=None,885        context=None,886        persist_config=True,887        client_configuration=None):888    """889    Loads configuration the same as load_kube_config but returns an ApiClient890    to be used with any API object. This will allow the caller to concurrently891    talk with multiple clusters.892    """893    if client_configuration is None:894        client_configuration = type.__call__(Configuration)895    load_kube_config(config_file=config_file, context=context,896                     client_configuration=client_configuration,897                     persist_config=persist_config)898    return ApiClient(configuration=client_configuration)899 900 901def new_client_from_config_dict(902        config_dict=None,903        context=None,904        persist_config=True,905        temp_file_path=None,906        client_configuration=None):907    """908    Loads configuration the same as load_kube_config_from_dict but returns an ApiClient909    to be used with any API object. This will allow the caller to concurrently910    talk with multiple clusters.911    """912    if client_configuration is None:913        client_configuration = type.__call__(Configuration)914    load_kube_config_from_dict(config_dict=config_dict, context=context,915                               client_configuration=client_configuration,916                               persist_config=persist_config,917                               temp_file_path=temp_file_path)918    return ApiClient(configuration=client_configuration)919 
codekingpro/portable-devtools · Team Ai