-
Notifications
You must be signed in to change notification settings - Fork 633
[k8s] allow use of "k8s" instead of "kubernetes" in the CLI and python API #4151
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
Conversation
8c7e681
to
ced3511
Compare
ced3511
to
96323b3
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.
Thanks @cg505!
sky/clouds/cloud_registry.py
Outdated
f'{list(self.clouds.keys())}') | ||
return self.clouds[name.lower()] | ||
|
||
def from_name_or_alias(self, |
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 from_name_or_alias and from_str do the same thing. For simplicity, should we just retain from_str()
and move this functionality there?
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.
Initially this is what I did, but there are cases where it's assumed that from_str
will only work for the "canonical" name of the cloud.
For instance, if I hadn't made changes to show_gpus
, updating from_str
would cause sky show-gpus --cloud k8s
to crash. Although this particular case is fixed by my changes, I'm worried there are other uses of from_str that rely on this behavior that I would be breaking.
raise ValueError(f'Cloud {name!r} is not a valid cloud name among ' | ||
f'{[*self.clouds.keys(), *self.aliases.keys()]}') | ||
|
||
def register( |
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.
Can we have register
support both syntax:
# Where no aliases required, not a callable
@ clouds.CLOUD_REGISTRY.register
# Callable where aliases are required:
clouds.CLOUD_REGISTRY.register(aliases=['k8s'])
Most python decorators follow this convention (e.g., @ray.remote
, @dataclass
...)
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.
Sure, I will look at those examples.
sky/cli.py
Outdated
cloud_obj = sky_clouds.CLOUD_REGISTRY.from_name_or_alias(cloud) | ||
cloud_name = None | ||
if cloud_obj is not None: | ||
cloud_name = type(cloud_obj).__name__.lower() |
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.
Might be a little cleaner to have a reverse lookup in CLOUD_REGISTRY
, e.g., CLOUD_REGISTRY.to_str(cloud)
?
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.
Thanks @cg505! Left some minor comments.
sky/clouds/cloud_registry.py
Outdated
|
||
from sky.utils import ux_utils | ||
|
||
if typing.TYPE_CHECKING: | ||
from sky.clouds import cloud | ||
|
||
|
||
class _CloudRegistry(dict): | ||
class _CloudRegistry: |
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.
Should we retain the previous behavior and have the cloud inherit from dict (keeps it pythonic, can do cloud_registry.CLOUD_REGISTRY.keys()
/.values()
instead of cloud_registry.CLOUD_REGISTRY.clouds.keys()
)
class _CloudRegistry(dict):
"""Registry of clouds."""
def __init__(self) -> None:
super().__init__()
self.aliases: Dict[str, str] = {}
def from_str(self, name: Optional[str]) -> Optional['cloud.Cloud']:
if name is None:
return None
search_name = name.lower()
if search_name in self:
return self[search_name]
if search_name in self.aliases:
return self[self.aliases[search_name]]
with ux_utils.print_exception_no_traceback():
raise ValueError(f'Cloud {name!r} is not a valid cloud among '
f'{[*self.keys(), *self.aliases.keys()]}')
@overload
def register(self, cloud_cls: Type['cloud.Cloud']) -> Type['cloud.Cloud']:
...
@overload
def register(
self,
cloud_cls: None = None,
aliases: Optional[List[str]] = None,
) -> Callable[[Type['cloud.Cloud']], Type['cloud.Cloud']]:
...
def register(
self,
cloud_cls: Optional[Type['cloud.Cloud']] = None,
aliases: Optional[List[str]] = None,
) -> Union[Type['cloud.Cloud'], Callable[[Type['cloud.Cloud']],
Type['cloud.Cloud']]]:
def _register(cloud_cls: Type['cloud.Cloud']) -> Type['cloud.Cloud']:
name = cloud_cls.canonical_name()
assert name not in self, f'{name} already registered'
self[name] = cloud_cls()
for alias in aliases or []:
assert alias not in self.aliases, (
f'alias {alias} already registered')
self.aliases[alias] = name
return cloud_cls
if cloud_cls is not None:
# invocation without parens (e.g. just `@register`)
return _register(cloud_cls)
# Invocation with parens (e.g. `@register(aliases=['alias'])`)
return _register
sky/clouds/cloud_registry.py
Outdated
f'{[*self.clouds.keys(), *self.aliases.keys()]}') | ||
|
||
@staticmethod | ||
def to_canonical_name(cloud: Optional['cloud.Cloud']) -> Optional[str]: |
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.
Thanks for adding cloud.canonical_name()! With that, looks like this method is redundant and can be removed since callers can directly call cloud.canonical_name()?
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.
This one supports optional values, but that's the only difference.
|
||
search_name = name.lower() |
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.
Should we add a quick docstr to define the exact behavior of from_str?
"""Returns the cloud instance from the canonical name or alias."""
Co-authored-by: Romil Bhardwaj <[email protected]>
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.
nice @cg505! lgtm.
sky.K8s()
can be used in place ofsky.Kubernetes()
sky check k8s
orsky launch --cloud k8s
will use Kubernetes as intended. Anywhere that CLOUD_REGISTRY.from_str() is used should work.Tested (run the relevant ones):
Need some advice on a good approach to write tests for this.
bash format.sh
pytest tests/test_smoke.py
pytest tests/test_smoke.py::test_fill_in_the_name
conda deactivate; bash -i tests/backward_compatibility_tests.sh