Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Part 3 of #205] Added utils for k8s model verification #232

Merged

Conversation

consideRatio
Copy link
Member

@consideRatio consideRatio commented Aug 9, 2018

About

Adding two utility functions that is not used yet, they are simply made available and tested in some unit tests. Perhaps this shouldn't been extracted as a separate PR as it is pointless if it is not used... Hmm...

  • get_k8s_model
  • update_k8s_model

About get_k8s_model(model_type, model_dict)

In KubeSpawner we handle dictionaries representing segments of resources strictly defined by the Kubernetes API. The user of KubeSpawner most often gives us dictionaries, but internally we could take these and create objects defined in the python kubernetes package such as V1Container for example, which can be importat with from kubernetes.client.models import V1Container.

get_k8s_model will take either a dict or kubernetes model object, but always returns a model object or fail attempting to create one. In this way, we will verify and fail fast if we provide faulty fields to kubespawner.

update_k8s_model(target, changes, logger=None, target_name=None, changes_name=None)

This function updates a model (target) in place with some fields that can be set on such model (source). It will also warn if the source, which is a model object of the same kind as target or a dict, is overriding a field in the target. When it performs the optional logging, it will use the target_name and changes_name parameters for some helpful tracing.

Copy link
Member Author

@consideRatio consideRatio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ask for some changes myself :D

@@ -27,3 +27,112 @@ def generate_hashed_slug(slug, limit=63, hash_length=6):
prefix=slug[:limit - hash_length - 1],
hash=slug_hash[:hash_length],
).lower()


def update_k8s_model(target, source, logger=None, origin=None):
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename origin to target_name, it would make it easier to understand the parameters function


return target

def get_k8s_model(model, model_dict):
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename model to model_type for clarity that model isn't an instance of the some kubernetes.client.model.<modelname> but actually the type of such model.

else:
raise AttributeError("Expected object of type 'dict' (or '{}') but got '{}'.".format(model.__type__.__name__, model_dict.__type__.__name__))

def _get_k8s_model_dict(model, obj):
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename model to model_type for clarity that model isn't an instance of the some kubernetes.client.model.<modelname> but actually the type of such model.

Note that the function will not influence nested object's keys.
"""

for key in list(model_dict.keys()):
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since i modify the model_dict while looping over its keys, I better loop over a copy of the keys rather than evaluating then while modifying them. So, I'm creating a new list from model_dict.keys() by passing it to list(), perhaps i should use copy() to make it more obvious?


return model_dict

def _get_k8s_model_attribute(model, field_name):
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make it clear that this parameter actually is a model instance.

@consideRatio consideRatio force-pushed the pr3-utils-for-model-verification branch from 83538fa to c44ee1a Compare August 9, 2018 12:36
# it is important to iterate over a copy of the dictionaries keys, as they
# will be updated in the loop
for key in list(model_dict.keys()):
model_dict[_get_k8s_model_attribute(model_type, key)] = model_dict.pop(key)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should create a new dictionary instead of mutating one in-place

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for considering this @minrk.

I'm intending to use this helper twice as written out below, this code is from PR Part 4.

    # the assignments to notebook_container and pod.spec is pointless atm, but won't be if I update the utility function update_k8s_model to be get_updated_copy_of_k8s_model or similar.
    if extra_container_config:
        notebook_container = update_k8s_model(
            target=notebook_container,
            changes=extra_container_config,
            logger=logger,
            target_name="extra_container_config",
        )

    # ...

    if extra_pod_config:
        pod.spec = update_k8s_model(
            target=pod.spec,
            changes=extra_pod_config,
            logger=logger,
            target_name="extra_pod_config",
        )

I reasoned that we are already making a lot of changes to notebook_container and pod.spec, and pod.spec will be a huge object relatively so I was thinking I wasn't sure that I could do a deepcopy and retain good enough performance. Also note that anything else than a deepcopy of objects like pod.spec containing a lot of nested reference objects would be misleading I think.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I trust your experience on this, so I'll go with whatever you think is best and be right on it, the change won't be causing much work at all if we do it!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm... target_name isn't right, it's really changes_name

@consideRatio consideRatio force-pushed the pr3-utils-for-model-verification branch from cdfd552 to a2cb445 Compare August 10, 2018 14:30
@consideRatio
Copy link
Member Author

@minrk I implemented the suggested changes, and made some improvements to docstrings etc.

I will now merge this unused code so I can rebase my next pr on top of this. Thanks for the review @minrk :heart!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants