diff --git a/config/dateutil.py b/config/dateutil.py index 924d1e30..9f432895 100644 --- a/config/dateutil.py +++ b/config/dateutil.py @@ -46,7 +46,7 @@ def dst(self, dt): def parse_rfc3339(s): - if type(s) == datetime.datetime: + if isinstance(s, datetime.datetime): # no need to parse it, just make sure it has a timezone. if not s.tzinfo: return s.replace(tzinfo=UTC) diff --git a/config/dateutil_test.py b/config/dateutil_test.py new file mode 100644 index 00000000..deb0ea88 --- /dev/null +++ b/config/dateutil_test.py @@ -0,0 +1,53 @@ +# Copyright 2016 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest +from datetime import datetime + +from .dateutil import UTC, TimezoneInfo, format_rfc3339, parse_rfc3339 + + +class DateUtilTest(unittest.TestCase): + + def _parse_rfc3339_test(self, st, y, m, d, h, mn, s): + actual = parse_rfc3339(st) + expected = datetime(y, m, d, h, mn, s, 0, UTC) + self.assertEqual(expected, actual) + + def test_parse_rfc3339(self): + self._parse_rfc3339_test("2017-07-25T04:44:21Z", + 2017, 7, 25, 4, 44, 21) + self._parse_rfc3339_test("2017-07-25 04:44:21Z", + 2017, 7, 25, 4, 44, 21) + self._parse_rfc3339_test("2017-07-25T04:44:21", + 2017, 7, 25, 4, 44, 21) + self._parse_rfc3339_test("2017-07-25T04:44:21z", + 2017, 7, 25, 4, 44, 21) + self._parse_rfc3339_test("2017-07-25T04:44:21+03:00", + 2017, 7, 25, 1, 44, 21) + self._parse_rfc3339_test("2017-07-25T04:44:21-03:00", + 2017, 7, 25, 7, 44, 21) + + def test_format_rfc3339(self): + self.assertEqual( + format_rfc3339(datetime(2017, 7, 25, 4, 44, 21, 0, UTC)), + "2017-07-25T04:44:21Z") + self.assertEqual( + format_rfc3339(datetime(2017, 7, 25, 4, 44, 21, 0, + TimezoneInfo(2, 0))), + "2017-07-25T02:44:21Z") + self.assertEqual( + format_rfc3339(datetime(2017, 7, 25, 4, 44, 21, 0, + TimezoneInfo(-2, 30))), + "2017-07-25T07:14:21Z") diff --git a/config/kube_config.py b/config/kube_config.py index 89b0d2c4..fdceadcd 100644 --- a/config/kube_config.py +++ b/config/kube_config.py @@ -22,10 +22,10 @@ import google.auth.transport.requests import urllib3 import yaml - from kubernetes.client import ApiClient, ConfigurationObject, configuration -from .dateutil import parse_rfc3339, format_rfc3339, UTC + from .config_exception import ConfigException +from .dateutil import UTC, format_rfc3339, parse_rfc3339 EXPIRY_SKEW_PREVENTION_DELAY = datetime.timedelta(minutes=5) KUBE_CONFIG_DEFAULT_LOCATION = os.environ.get('KUBECONFIG', '~/.kube/config') @@ -320,11 +320,6 @@ def _get_kube_config_loader_for_yaml_file(filename, **kwargs): **kwargs) -def _save_kube_config(filename, config_map): - with open(filename, 'w') as f: - yaml.safe_dump(config_map, f, default_flow_style=False) - - def list_kube_config_contexts(config_file=None): if config_file is None: @@ -354,8 +349,11 @@ def load_kube_config(config_file=None, context=None, config_persister = None if persist_config: - config_persister = lambda config_map, config_file=config_file: ( - _save_kube_config(config_file, config_map)) + def _save_kube_config(config_map): + with open(config_file, 'w') as f: + yaml.safe_dump(config_map, f, default_flow_style=False) + config_persister = _save_kube_config + _get_kube_config_loader_for_yaml_file( config_file, active_context=context, client_configuration=client_configuration, diff --git a/config/kube_config_test.py b/config/kube_config_test.py index 6cea0ab0..6fa48b60 100644 --- a/config/kube_config_test.py +++ b/config/kube_config_test.py @@ -23,11 +23,11 @@ from six import PY3 from .config_exception import ConfigException +from .dateutil import parse_rfc3339 from .kube_config import (ConfigNode, FileOrData, KubeConfigLoader, _cleanup_temp_files, _create_temp_file_with_content, list_kube_config_contexts, load_kube_config, new_client_from_config) -from .rfc3339 import timestamp_from_tf BEARER_TOKEN_FORMAT = "Bearer %s" @@ -38,6 +38,10 @@ def _base64(string): return base64.encodestring(string.encode()).decode() +def _raise_exception(st): + raise Exception(st) + + TEST_FILE_KEY = "file" TEST_DATA_KEY = "data" TEST_FILENAME = "test-filename" @@ -422,7 +426,7 @@ class TestKubeConfigLoader(BaseTestCase): "name": "gcp", "config": { "access-token": TEST_DATA_BASE64, - "expiry": timestamp_from_tf(0), + "expiry": "2000-01-01T12:00:00Z", # always in past } }, "token": TEST_DATA_BASE64, # should be ignored @@ -499,15 +503,16 @@ def test_gcp_no_refresh(self): config_dict=self.TEST_KUBE_CONFIG, active_context="gcp", client_configuration=actual, - get_google_credentials=lambda: "SHOULD NOT BE CALLED") \ - .load_and_set() + get_google_credentials=lambda: _raise_exception( + "SHOULD NOT BE CALLED")).load_and_set() self.assertEqual(expected, actual) def test_load_gcp_token_no_refresh(self): loader = KubeConfigLoader( config_dict=self.TEST_KUBE_CONFIG, active_context="gcp", - get_google_credentials=lambda: "SHOULD NOT BE CALLED") + get_google_credentials=lambda: _raise_exception( + "SHOULD NOT BE CALLED")) self.assertTrue(loader._load_gcp_token()) self.assertEqual(BEARER_TOKEN_FORMAT % TEST_DATA_BASE64, loader.token)