diff --git a/paasta_tools/kubernetes_tools.py b/paasta_tools/kubernetes_tools.py index 5151d42acf..b86b2aa4f9 100644 --- a/paasta_tools/kubernetes_tools.py +++ b/paasta_tools/kubernetes_tools.py @@ -43,10 +43,10 @@ from humanfriendly import parse_size from kubernetes import client as kube_client from kubernetes import config as kube_config -from kubernetes.client import CoreV1Event from kubernetes.client import models from kubernetes.client import V1Affinity from kubernetes.client import V1AWSElasticBlockStoreVolumeSource +from kubernetes.client import V1beta1CustomResourceDefinition from kubernetes.client import V1beta1PodDisruptionBudget from kubernetes.client import V1beta1PodDisruptionBudgetSpec from kubernetes.client import V1Capabilities @@ -55,7 +55,6 @@ from kubernetes.client import V1ContainerPort from kubernetes.client import V1ContainerStatus from kubernetes.client import V1ControllerRevision -from kubernetes.client import V1CustomResourceDefinition from kubernetes.client import V1CustomResourceDefinitionList from kubernetes.client import V1DeleteOptions from kubernetes.client import V1Deployment @@ -63,13 +62,14 @@ from kubernetes.client import V1DeploymentStrategy from kubernetes.client import V1EnvVar from kubernetes.client import V1EnvVarSource +from kubernetes.client import V1Event from kubernetes.client import V1ExecAction +from kubernetes.client import V1Handler from kubernetes.client import V1HostPathVolumeSource from kubernetes.client import V1HTTPGetAction from kubernetes.client import V1KeyToPath from kubernetes.client import V1LabelSelector from kubernetes.client import V1Lifecycle -from kubernetes.client import V1LifecycleHandler from kubernetes.client import V1Namespace from kubernetes.client import V1Node from kubernetes.client import V1NodeAffinity @@ -525,7 +525,7 @@ def __init__( self.deployments = kube_client.AppsV1Api(self.api_client) self.core = kube_client.CoreV1Api(self.api_client) self.policy = kube_client.PolicyV1beta1Api(self.api_client) - self.apiextensions = kube_client.ApiextensionsV1Api(self.api_client) + self.apiextensions = kube_client.ApiextensionsV1beta1Api(self.api_client) self.custom = kube_client.CustomObjectsApi(self.api_client) self.autoscaling = kube_client.AutoscalingV2beta2Api(self.api_client) self.rbac = kube_client.RbacAuthorizationV1Api(self.api_client) @@ -1025,7 +1025,7 @@ def get_hacheck_sidecar_container( return V1Container( image=system_paasta_config.get_hacheck_sidecar_image_url(), lifecycle=V1Lifecycle( - pre_stop=V1LifecycleHandler( + pre_stop=V1Handler( _exec=V1ExecAction( command=[ "/bin/sh", @@ -1067,7 +1067,7 @@ def get_uwsgi_exporter_sidecar_container( env=self.get_kubernetes_environment() + [stats_port_env], ports=[V1ContainerPort(container_port=9117)], lifecycle=V1Lifecycle( - pre_stop=V1LifecycleHandler( + pre_stop=V1Handler( _exec=V1ExecAction( command=[ "/bin/sh", @@ -1377,20 +1377,20 @@ def get_readiness_probe( else: return self.get_liveness_probe(service_namespace_config) - def get_kubernetes_container_termination_action(self) -> V1LifecycleHandler: + def get_kubernetes_container_termination_action(self) -> V1Handler: command = self.config_dict.get("lifecycle", KubeLifecycleDict({})).get( "pre_stop_command", [] ) # default pre stop hook for the container if not command: - return V1LifecycleHandler( + return V1Handler( _exec=V1ExecAction( command=["/bin/sh", "-c", f"sleep {DEFAULT_PRESTOP_SLEEP_SECONDS}"] ) ) if isinstance(command, str): command = [command] - return V1LifecycleHandler(_exec=V1ExecAction(command=command)) + return V1Handler(_exec=V1ExecAction(command=command)) def get_pod_volumes( self, @@ -3294,7 +3294,7 @@ def update_stateful_set( ) -def get_event_timestamp(event: CoreV1Event) -> Optional[float]: +def get_event_timestamp(event: V1Event) -> Optional[float]: # Cycle through timestamp attributes in order of preference for ts_attr in ["last_timestamp", "event_time", "first_timestamp"]: ts = getattr(event, ts_attr) @@ -3309,7 +3309,7 @@ async def get_events_for_object( obj: Union[V1Pod, V1Deployment, V1StatefulSet, V1ReplicaSet], kind: str, # for some reason, obj.kind isn't populated when this function is called so we pass it in by hand max_age_in_seconds: Optional[int] = None, -) -> List[CoreV1Event]: +) -> List[V1Event]: try: # this is a blocking call since it does network I/O and can end up significantly blocking the @@ -3800,7 +3800,7 @@ def mode_to_int(mode: Optional[Union[str, int]]) -> Optional[int]: def update_crds( kube_client: KubeClient, - desired_crds: Collection[V1CustomResourceDefinition], + desired_crds: Collection[V1beta1CustomResourceDefinition], existing_crds: V1CustomResourceDefinitionList, ) -> bool: success = True diff --git a/paasta_tools/setup_kubernetes_crd.py b/paasta_tools/setup_kubernetes_crd.py index 856a9d4136..9e85e45fa7 100644 --- a/paasta_tools/setup_kubernetes_crd.py +++ b/paasta_tools/setup_kubernetes_crd.py @@ -27,7 +27,7 @@ from typing import Sequence import service_configuration_lib -from kubernetes.client import V1CustomResourceDefinition +from kubernetes.client import V1beta1CustomResourceDefinition from paasta_tools.kubernetes_tools import KubeClient from paasta_tools.kubernetes_tools import paasta_prefixed @@ -118,7 +118,7 @@ def setup_kube_crd( metadata["labels"] = {} metadata["labels"]["yelp.com/paasta_service"] = service metadata["labels"][paasta_prefixed("service")] = service - desired_crd = V1CustomResourceDefinition( + desired_crd = V1beta1CustomResourceDefinition( api_version=crd_config.get("apiVersion"), kind=crd_config.get("kind"), metadata=metadata, diff --git a/paasta_tools/setup_kubernetes_internal_crd.py b/paasta_tools/setup_kubernetes_internal_crd.py index 0d1d3e2778..807d080ac1 100755 --- a/paasta_tools/setup_kubernetes_internal_crd.py +++ b/paasta_tools/setup_kubernetes_internal_crd.py @@ -23,7 +23,7 @@ import logging import sys -from kubernetes.client import V1CustomResourceDefinition +from kubernetes.client import V1beta1CustomResourceDefinition from paasta_tools.kubernetes_tools import KubeClient from paasta_tools.kubernetes_tools import paasta_prefixed @@ -33,8 +33,8 @@ INTERNAL_CRDS = [ - V1CustomResourceDefinition( - api_version="apiextensions.k8s.io/v1", + V1beta1CustomResourceDefinition( + api_version="apiextensions.k8s.io/v1beta1", kind="CustomResourceDefinition", metadata={ "name": "deploygroups.paasta.yelp.com", @@ -44,24 +44,7 @@ }, spec={ "group": "paasta.yelp.com", - "versions": [ - { - "name": "v1beta1", - "served": True, - "storage": True, - "schema": { - "openAPIV3Schema": { - "type": "object", - "properties": { - "service": {"type": "string"}, - "deploy_group": {"type": "string"}, - "git_sha": {"type": "string"}, - "image_version": {"type": "string"}, - }, - } - }, - } - ], + "versions": [{"name": "v1beta1", "served": True, "storage": True}], "scope": "Namespaced", "names": { "plural": "deploygroups", @@ -69,10 +52,21 @@ "kind": "DeployGroup", "shortNames": ["dg"], }, + "validation": { + "openAPIV3Schema": { + "type": "object", + "properties": { + "service": {"type": "string"}, + "deploy_group": {"type": "string"}, + "git_sha": {"type": "string"}, + "image_version": {"type": "string"}, + }, + } + }, }, ), - V1CustomResourceDefinition( - api_version="apiextensions.k8s.io/v1", + V1beta1CustomResourceDefinition( + api_version="apiextensions.k8s.io/v1beta1", kind="CustomResourceDefinition", metadata={ "name": "startstopcontrols.paasta.yelp.com", @@ -82,30 +76,24 @@ }, spec={ "group": "paasta.yelp.com", - "versions": [ - { - "name": "v1beta1", - "served": True, - "storage": True, - "schema": { - "openAPIV3Schema": { - "type": "object", - "properties": { - "service": {"type": "string"}, - "instance": {"type": "string"}, - "desired_state": {"type": "string"}, - "force_bounce": {"type": "string"}, - }, - } - }, - } - ], + "versions": [{"name": "v1beta1", "served": True, "storage": True}], "scope": "Namespaced", "names": { "plural": "startstopcontrols", "singular": "startstopcontrol", "kind": "StartStopControl", }, + "validation": { + "openAPIV3Schema": { + "type": "object", + "properties": { + "service": {"type": "string"}, + "instance": {"type": "string"}, + "desired_state": {"type": "string"}, + "force_bounce": {"type": "string"}, + }, + } + }, }, ), ] diff --git a/requirements.txt b/requirements.txt index 65296519c3..5cb662dbc7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -44,7 +44,7 @@ jmespath==0.9.3 jsonref==0.1 jsonschema==2.5.1 kazoo==2.8.0 -kubernetes==24.2.0 +kubernetes==18.20.0 ldap3==2.6 manhole==1.5.0 marathon==0.12.0 diff --git a/tests/test_kubernetes_tools.py b/tests/test_kubernetes_tools.py index 986de4cf69..92fa903e12 100644 --- a/tests/test_kubernetes_tools.py +++ b/tests/test_kubernetes_tools.py @@ -24,12 +24,12 @@ from kubernetes.client import V1EnvVar from kubernetes.client import V1EnvVarSource from kubernetes.client import V1ExecAction +from kubernetes.client import V1Handler from kubernetes.client import V1HostPathVolumeSource from kubernetes.client import V1HTTPGetAction from kubernetes.client import V1KeyToPath from kubernetes.client import V1LabelSelector from kubernetes.client import V1Lifecycle -from kubernetes.client import V1LifecycleHandler from kubernetes.client import V1NodeAffinity from kubernetes.client import V1NodeSelector from kubernetes.client import V1NodeSelectorRequirement @@ -559,7 +559,7 @@ def test_get_sidecar_containers(self): ], image="some-docker-image", lifecycle=V1Lifecycle( - pre_stop=V1LifecycleHandler( + pre_stop=V1Handler( _exec=V1ExecAction( command=[ "/bin/sh", @@ -605,7 +605,7 @@ def test_get_sidecar_containers(self): ], image="some-docker-image", lifecycle=V1Lifecycle( - pre_stop=V1LifecycleHandler( + pre_stop=V1Handler( _exec=V1ExecAction( command=[ "/bin/sh", @@ -1005,7 +1005,7 @@ def test_get_kubernetes_containers(self, prometheus_port, expected_ports): resources=mock_get_resource_requirements.return_value, image=mock_get_docker_url.return_value, lifecycle=V1Lifecycle( - pre_stop=V1LifecycleHandler( + pre_stop=V1Handler( _exec=V1ExecAction(command=["/bin/sh", "-c", "sleep 30"]) ) ), @@ -1949,7 +1949,7 @@ def test_kubernetes_container_termination_action( self.deployment.config_dict["lifecycle"] = { "pre_stop_command": termination_action } - handler = V1LifecycleHandler(_exec=V1ExecAction(command=expected)) + handler = V1Handler(_exec=V1ExecAction(command=expected)) assert self.deployment.get_kubernetes_container_termination_action() == handler @pytest.mark.parametrize( @@ -3965,7 +3965,7 @@ def test_warning_big_bounce(): job_config.format_kubernetes_app().spec.template.metadata.labels[ "paasta.yelp.com/config_sha" ] - == "configd6531f39" + == "configf6939dba" ), "If this fails, just change the constant in this test, but be aware that deploying this change will cause every service to bounce!" @@ -4011,7 +4011,7 @@ def test_warning_big_bounce_routable_pod(): job_config.format_kubernetes_app().spec.template.metadata.labels[ "paasta.yelp.com/config_sha" ] - == "configa5abd828" + == "config0107126a" ), "If this fails, just change the constant in this test, but be aware that deploying this change will cause every smartstack-registered service to bounce!"