fix(kubernetes): temporary solution for updated k8s python client
This commit is contained in:
parent
07d6fe7442
commit
9129813244
1478 changed files with 422354 additions and 2 deletions
174
kubernetes/utils/duration.py
Normal file
174
kubernetes/utils/duration.py
Normal file
|
@ -0,0 +1,174 @@
|
|||
# Copyright 2024 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.
|
||||
from typing import List
|
||||
|
||||
import datetime
|
||||
import re
|
||||
|
||||
import durationpy
|
||||
|
||||
# Initialize our RE statically, rather than compiling for every call. This has
|
||||
# the downside that it'll get compiled at import time but that shouldn't
|
||||
# really be a big deal.
|
||||
reDuration = re.compile(r'^([0-9]{1,5}(h|m|s|ms)){1,4}$')
|
||||
|
||||
# maxDuration_ms is the maximum duration that GEP-2257 can support, in
|
||||
# milliseconds.
|
||||
maxDuration_ms = (((99999 * 3600) + (59 * 60) + 59) * 1_000) + 999
|
||||
|
||||
|
||||
def parse_duration(duration) -> datetime.timedelta:
|
||||
"""
|
||||
Parse GEP-2257 Duration format to a datetime.timedelta object.
|
||||
|
||||
The GEP-2257 Duration format is a restricted form of the input to the Go
|
||||
time.ParseDuration function; specifically, it must match the regex
|
||||
"^([0-9]{1,5}(h|m|s|ms)){1,4}$".
|
||||
|
||||
See https://gateway-api.sigs.k8s.io/geps/gep-2257/ for more details.
|
||||
|
||||
Input: duration: string
|
||||
Returns: datetime.timedelta
|
||||
|
||||
Raises: ValueError on invalid or unknown input
|
||||
|
||||
Examples:
|
||||
>>> parse_duration("1h")
|
||||
datetime.timedelta(seconds=3600)
|
||||
>>> parse_duration("1m")
|
||||
datetime.timedelta(seconds=60)
|
||||
>>> parse_duration("1s")
|
||||
datetime.timedelta(seconds=1)
|
||||
>>> parse_duration("1ms")
|
||||
datetime.timedelta(microseconds=1000)
|
||||
>>> parse_duration("1h1m1s")
|
||||
datetime.timedelta(seconds=3661)
|
||||
>>> parse_duration("10s30m1h")
|
||||
datetime.timedelta(seconds=5410)
|
||||
|
||||
Units are always required.
|
||||
>>> parse_duration("1")
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: Invalid duration format: 1
|
||||
|
||||
Floating-point and negative durations are not valid.
|
||||
>>> parse_duration("1.5m")
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: Invalid duration format: 1.5m
|
||||
>>> parse_duration("-1m")
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: Invalid duration format: -1m
|
||||
"""
|
||||
|
||||
if not reDuration.match(duration):
|
||||
raise ValueError("Invalid duration format: {}".format(duration))
|
||||
|
||||
return durationpy.from_str(duration)
|
||||
|
||||
|
||||
def format_duration(delta: datetime.timedelta) -> str:
|
||||
"""
|
||||
Format a datetime.timedelta object to GEP-2257 Duration format.
|
||||
|
||||
The GEP-2257 Duration format is a restricted form of the input to the Go
|
||||
time.ParseDuration function; specifically, it must match the regex
|
||||
"^([0-9]{1,5}(h|m|s|ms)){1,4}$".
|
||||
|
||||
See https://gateway-api.sigs.k8s.io/geps/gep-2257/ for more details.
|
||||
|
||||
Input: duration: datetime.timedelta
|
||||
|
||||
Returns: string
|
||||
|
||||
Raises: ValueError if the timedelta given cannot be expressed as a
|
||||
GEP-2257 Duration.
|
||||
|
||||
Examples:
|
||||
>>> format_duration(datetime.timedelta(seconds=3600))
|
||||
'1h'
|
||||
>>> format_duration(datetime.timedelta(seconds=60))
|
||||
'1m'
|
||||
>>> format_duration(datetime.timedelta(seconds=1))
|
||||
'1s'
|
||||
>>> format_duration(datetime.timedelta(microseconds=1000))
|
||||
'1ms'
|
||||
>>> format_duration(datetime.timedelta(seconds=5410))
|
||||
'1h30m10s'
|
||||
|
||||
The zero duration is always "0s".
|
||||
>>> format_duration(datetime.timedelta(0))
|
||||
'0s'
|
||||
|
||||
Sub-millisecond precision is not allowed.
|
||||
>>> format_duration(datetime.timedelta(microseconds=100))
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: Cannot express sub-millisecond precision in GEP-2257: 0:00:00.000100
|
||||
|
||||
Negative durations are not allowed.
|
||||
>>> format_duration(datetime.timedelta(seconds=-1))
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: Cannot express negative durations in GEP-2257: -1 day, 23:59:59
|
||||
"""
|
||||
|
||||
# Short-circuit if we have a zero delta.
|
||||
if delta == datetime.timedelta(0):
|
||||
return "0s"
|
||||
|
||||
# Check range early.
|
||||
if delta < datetime.timedelta(0):
|
||||
raise ValueError("Cannot express negative durations in GEP-2257: {}".format(delta))
|
||||
|
||||
if delta > datetime.timedelta(milliseconds=maxDuration_ms):
|
||||
raise ValueError(
|
||||
"Cannot express durations longer than 99999h59m59s999ms in GEP-2257: {}".format(delta))
|
||||
|
||||
# durationpy.to_str() is happy to use floating-point seconds, which
|
||||
# GEP-2257 is _not_ happy with. So start by peeling off any microseconds
|
||||
# from our delta.
|
||||
delta_us = delta.microseconds
|
||||
|
||||
if (delta_us % 1000) != 0:
|
||||
raise ValueError(
|
||||
"Cannot express sub-millisecond precision in GEP-2257: {}"
|
||||
.format(delta)
|
||||
)
|
||||
|
||||
# After that, do the usual div & mod tree to take seconds and get hours,
|
||||
# minutes, and seconds from it.
|
||||
secs = int(delta.total_seconds())
|
||||
|
||||
output: List[str] = []
|
||||
|
||||
hours = secs // 3600
|
||||
if hours > 0:
|
||||
output.append(f"{hours}h")
|
||||
secs -= hours * 3600
|
||||
|
||||
minutes = secs // 60
|
||||
if minutes > 0:
|
||||
output.append(f"{minutes}m")
|
||||
secs -= minutes * 60
|
||||
|
||||
if secs > 0:
|
||||
output.append(f"{secs}s")
|
||||
|
||||
if delta_us > 0:
|
||||
output.append(f"{delta_us // 1000}ms")
|
||||
|
||||
return "".join(output)
|
Reference in a new issue