-
Notifications
You must be signed in to change notification settings - Fork 185
Add proper GCP config loader and refresher #22
Conversation
Thanks! |
@gabrielgbim @pokoli This is a release blocker. Can you review it please. |
f4da0c7
to
253d937
Compare
Codecov Report
@@ Coverage Diff @@
## master #22 +/- ##
==========================================
- Coverage 94.69% 93.64% -1.06%
==========================================
Files 9 11 +2
Lines 698 803 +105
==========================================
+ Hits 661 752 +91
- Misses 37 51 +14
Continue to review full report at Codecov.
|
config/kube_config.py
Outdated
@@ -54,6 +59,17 @@ def _create_temp_file_with_content(content): | |||
return name | |||
|
|||
|
|||
def _is_expired(expiry): | |||
tf = tf_from_timestamp(expiry) | |||
n = time.time() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think you need to store n as a variable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
config/kube_config.py
Outdated
@@ -308,21 +353,32 @@ def load_kube_config(config_file=None, context=None, | |||
from config file will be used. | |||
:param client_configuration: The kubernetes.client.ConfigurationObject to | |||
set configs to. | |||
:param persist_config: If True and config changed (e.g. GCP token refresh) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe better: "IF True config file will be updated when changed (e.g GCP token refresh)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed!
config/kube_config.py
Outdated
""" | ||
|
||
if config_file is None: | ||
config_file = os.path.expanduser(KUBE_CONFIG_DEFAULT_LOCATION) | ||
|
||
config_persister = None | ||
if persist_config: | ||
config_persister = lambda config_map, config_file=config_file: ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is required a lambda function here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to pass the config_file to _save_kube_config. If there is a better way to do it, I am open to it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIU it should work with:
config_persister = _save_kube_config
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the key here is the config_file=config_file:
part that passes the local variable config_file as one of the parameters.
config_persisteraccepts one parameter,
_save_kube_config` needs two.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I didn't understand at all the code.
Then you should probably use the partial function from functools standard library.
This will make the code clearer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I inline'ed _save_kube_config
. it should be cleaner. is it good or do you still suggest partial function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, now the usage it's much clearer.
config/kube_config_test.py
Outdated
actual = FakeConfig() | ||
KubeConfigLoader( | ||
config_dict=self.TEST_KUBE_CONFIG, | ||
active_context="gcp", | ||
client_configuration=actual, | ||
get_google_credentials=lambda: TEST_ANOTHER_DATA_BASE64) \ | ||
get_google_credentials=lambda: "SHOULD NOT BE CALLED") \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe you can put a raise to ensure it's not called
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will fix this with some other tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
config/rfc3339.MD
Outdated
@@ -0,0 +1 @@ | |||
The (rfc3339.py)[rfc3339.py] file is copied from [this site](http://home.blarg.net/~steveha/pyfeed.html) because PyFeed is not available in PyPi. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about https://pypi.python.org/pypi/rfc3339/5.2 (source code in https://bitbucket.org/henry/rfc3339/src)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks like they only do one side of conversion? https://bitbucket.org/henry/rfc3339/issues/3/datetime-to-rfc-3339
I see a parse method but it is not exported.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then probably it's worth to contribute one to the library :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True. This is, however, a release blocker and I don't want to wait for that contribution to go through. I suggest we proceed with this and either contribute to the that one or even release the one I copied as a pypi package for all to use (I have a feeling by looking at the code that this one is better, but we can decide on that later).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've looked at different options and decided to implement my own. Some options are too restrictive for our use and the others are too admissive. I've implemented a simple balanced one in dateutil.py
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, as it's a release blocker I think the unique option we have is to include the code in the client.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the record, I didn't copy code from any of those libraries. I've implemented it again by reading rfc. Of course my implementation can be influenced by those libraries, but I stick to the rules of rfc3339. None of the libraries I've checked were like that, they were either relaxer or stricter. Also our implementation forces a UTC timezone.
@pokoli I am going to add some tests for dateutil but this is basically ready for review and I already tested it for GKE. Please take another look. I would like to merge this as soon as possible to cut a new release. |
5d0b367
to
50f717d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should probably need some test for the dateutil module.
config/kube_config.py
Outdated
""" | ||
|
||
if config_file is None: | ||
config_file = os.path.expanduser(KUBE_CONFIG_DEFAULT_LOCATION) | ||
|
||
config_persister = None | ||
if persist_config: | ||
config_persister = lambda config_map, config_file=config_file: ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIU it should work with:
config_persister = _save_kube_config
c4b8c87
to
bd507f4
Compare
Thanks for the review @pokoli I think I addressed all of your comments and tests are passing. Can you take a final look please? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Despite two minor issues its a LGTM
config/kube_config.py
Outdated
@@ -308,21 +341,35 @@ def load_kube_config(config_file=None, context=None, | |||
from config file will be used. | |||
:param client_configuration: The kubernetes.client.ConfigurationObject to | |||
set configs to. | |||
:param persist_config: IF True, config file will be updated when changed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IF -> If
@@ -36,6 +38,10 @@ def _base64(string): | |||
return base64.encodestring(string.encode()).decode() | |||
|
|||
|
|||
def _raise_exception(st): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not directly raising the exception?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you mean? I am passing this function as a function pointer to config loader and expect the function pointer (that suppose to update GCE token) never been called in the test. I was using lambda syntax to return a dummy token before, but you cannot raise exception in lambda syntax.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I didn't now that you can not raise inside lambda (always learning from codereview).
Forget about it.
@mbohlool for me you can merge once fixed. |
This is based on #21. I added expiration mechanism as well as persisting config back so we don't need to refresh the token every time. The way it persisted back should be the same as
kubectl
.Tests will fail for this PR unless kubernetes-client/python#302 is merged.